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을 포함하여 널리 사용되는 기타 서버 구현 을 다루었습니다  .

항상 그렇듯이 전체 소스 코드는 GitHub에서 사용할 수 있습니다 .

Junit footer banner