1. 개요
Java 애플리케이션에서 소켓 서버를 시작할 때 java.net API는 수신 대기할 여유 포트 번호를 지정하도록 요구합니다. 포트 번호는 TCP 계층이 들어오는 데이터가 의도된 응용 프로그램을 식별할 수 있도록 하는 데 필요합니다.
포트 번호를 명시적으로 지정하는 것이 항상 좋은 옵션은 아닙니다. 애플리케이션이 이미 포트 번호를 점유하고 있을 수 있기 때문입니다. 이로 인해 Java 애플리케이션에서 입력/출력 예외가 발생합니다.
이 빠른 사용방법(예제)에서는 특정 포트 상태를 확인하는 방법과 자동으로 할당된 포트를 사용하는 방법을 살펴보겠습니다. 일반 Java 및 Spring 프레임워크를 사용하여 이 작업을 수행하는 방법을 살펴보겠습니다. 임베디드 Tomcat 및 Jetty와 같은 다른 서버 구현도 살펴보겠습니다.
2. 포트 상태 확인
java.net API를 사용하여 특정 포트가 비어 있거나 점유되어 있는지 확인하는 방법을 살펴보겠습니다 .
2.1. S pecific 포트
java.net API 의 ServerSocket 클래스 를 사용하여 지정된 포트에 바인딩된 서버 소켓을 만듭니다. 생성자 에서 ServerSocket 은 명시적 포트 번호를 허용합니다. 클래스는 또한 Closeable 인터페이스를 구현 하므로 try-with-resources 에서 소켓을 자동으로 닫고 포트를 해제하는 데 사용할 수 있습니다 .
try (ServerSocket serverSocket = new ServerSocket(FREE_PORT_NUMBER)) {
assertThat(serverSocket).isNotNull();
assertThat(serverSocket.getLocalPort()).isEqualTo(FREE_PORT_NUMBER);
} catch (IOException e) {
fail("Port is not available");
}
특정 포트를 두 번 사용하거나 이미 다른 응용 프로그램에서 사용 중인 경우 ServerSocket 생성자는 IOException을 발생 시킵니다 .
try (ServerSocket serverSocket = new ServerSocket(FREE_PORT_NUMBER)) {
new ServerSocket(FREE_PORT_NUMBER);
fail("Same port cannot be used twice");
} catch (IOException e) {
assertThat(e).hasMessageContaining("Address already in use");
}
2.2. P 오트 범위
이제 주어진 범위의 포트 번호에서 첫 번째 자유 포트를 사용하여 서버 소켓을 생성하기 위해 throw된 IOException을 어떻게 사용할 수 있는지 확인하겠습니다 .
for (int port : FREE_PORT_RANGE) {
try (ServerSocket serverSocket = new ServerSocket(port)) {
assertThat(serverSocket).isNotNull();
assertThat(serverSocket.getLocalPort()).isEqualTo(port);
return;
} catch (IOException e) {
assertThat(e).hasMessageContaining("Address already in use");
}
}
fail("No free port in the range found");
3. 찾기 무료 포트
명시적 포트 번호를 사용하는 것이 항상 좋은 옵션은 아니므로 여유 포트를 자동으로 할당하는 가능성을 살펴보겠습니다.
3.1. 일반 자바
ServerSocket 클래스 생성자 에서 특수 포트 번호 0을 사용할 수 있습니다 . 결과적으로 java.net API는 자동으로 무료 포트를 할당합니다.
try (ServerSocket serverSocket = new ServerSocket(0)) {
assertThat(serverSocket).isNotNull();
assertThat(serverSocket.getLocalPort()).isGreaterThan(0);
} catch (IOException e) {
fail("Port is not available");
}
3.2. 스프링 프레임워크
Spring 프레임워크에는 사용 가능한 무료 포트를 찾는 데 사용할 수 있는 SocketUtils 클래스가 포함되어 있습니다 . 내부 구현은 이전 예제와 같이 ServerSocket 클래스를 사용합니다 .
int port = SocketUtils.findAvailableTcpPort();
try (ServerSocket serverSocket = new ServerSocket(port)) {
assertThat(serverSocket).isNotNull();
assertThat(serverSocket.getLocalPort()).isEqualTo(port);
} catch (IOException e) {
fail("Port is not available");
}
4. 기타 서버 구현
이제 다른 인기 있는 서버 구현을 살펴보겠습니다.
4.1. 둑
Jetty는 Java 애플리케이션용 으로 매우 인기 있는 임베디드 서버 입니다. ServerConnector 클래스 의 setPort 메서드를 통해 명시적으로 설정하지 않는 한 자동으로 여유 포트를 할당합니다 .
Server jettyServer = new Server();
ServerConnector serverConnector = new ServerConnector(jettyServer);
jettyServer.addConnector(serverConnector);
try {
jettyServer.start();
assertThat(serverConnector.getLocalPort()).isGreaterThan(0);
} catch (Exception e) {
fail("Failed to start Jetty server");
} finally {
jettyServer.stop();
jettyServer.destroy();
}
4.2. 수코양이
또 다른 인기 있는 Java 임베디드 서버인 Tomcat 은 약간 다르게 작동합니다. Tomcat 클래스 의 setPort 메소드를 통해 명시적 포트 번호를 지정할 수 있습니다 . 포트 번호 0을 제공하는 경우 Tomcat은 자동으로 여유 포트를 할당합니다. 그러나 포트 번호를 설정하지 않으면 Tomcat은 기본 포트 8080을 사용합니다. 기본 Tomcat 포트는 다른 응용 프로그램이 차지할 수 있습니다.
Tomcat tomcatServer = new Tomcat();
tomcatServer.setPort(0);
try {
tomcatServer.start();
assertThat(tomcatServer.getConnector().getLocalPort()).isGreaterThan(0);
} catch (LifecycleException e) {
fail("Failed to start Tomcat server");
} finally {
tomcatServer.stop();
tomcatServer.destroy();
}
5. 결론
이 기사에서는 특정 포트 상태를 확인하는 방법을 살펴보았습니다. 또한 다양한 포트 번호에서 여유 포트를 찾는 방법과 자동으로 할당된 여유 포트를 사용하는 방법을 설명했습니다.
예제에서 우리 는 java.net API 의 기본 ServerSocket 클래스 와 Jetty 및 Tomcat을 포함하여 널리 사용되는 기타 서버 구현 을 다루었습니다 .