사용 가능한 포트를 찾는 방법은 무엇입니까?


195

포트를 수신하는 서버를 시작하고 싶습니다. 포트를 명시 적으로 지정할 수 있으며 작동합니다. 그러나 자동 방식으로 포트를 찾고 싶습니다. 이와 관련하여 두 가지 질문이 있습니다.

  1. 어떤 포트 번호 범위에서 검색해야합니까? (포트 12345, 12346 및 12347을 사용했는데 문제가 없었습니다).

  2. 특정 포트가 다른 소프트웨어를 사용하지 않는지 어떻게 알 수 있습니까?

답변:


280

사용 된 포트가 마음에 들지 않으면 ServerSocket 생성자에 포트 0을 지정하면 사용 가능한 포트에서 수신 대기합니다.

ServerSocket s = new ServerSocket(0);
System.out.println("listening on port: " + s.getLocalPort());

특정 포트 세트를 사용하려면 가장 쉬운 방법은 작동 할 때까지 해당 포트를 반복하는 것입니다. 이 같은:

public ServerSocket create(int[] ports) throws IOException {
    for (int port : ports) {
        try {
            return new ServerSocket(port);
        } catch (IOException ex) {
            continue; // try next port
        }
    }

    // if the program gets here, no port in the range was found
    throw new IOException("no free port found");
}

다음과 같이 사용할 수 있습니다.

try {
    ServerSocket s = create(new int[] { 3843, 4584, 4843 });
    System.out.println("listening on port: " + s.getLocalPort());
} catch (IOException ex) {
    System.err.println("no available ports");
}

2
새 ServerSocket (0)을 사용할 때는 닫을 때주의해야합니다! javasourcecode.org/html/open-source/eclipse/eclipse-3.5.2/org/…를 기반으로 내 gist.github.com/3429822에
vorburger

9
@vorburger, 그런 식으로하는 것은 경쟁 조건에 취약합니다. 사용 가능한 포트를 찾아서 다시 닫은 다음 사용 가능한 포트에서 다시 열지 않고 즉시 서버 소켓에서 수신 대기하는 것이 더 좋습니다. port.)
Graham Edgecombe

7
동의하지만 정확한 유스 케이스에 달려 있습니다. 제 경우에는 테스트를 위해 내장 된 Jetty 스타터와 같은 일부 API로 전달할 무료 포트 번호를 찾아야했습니다. 각 API는 소켓 번호를 원합니다. 서버 소켓을 열었습니다. 따라서 다릅니다.
vorburger

4
@vorburger 합리적인 API는 수신 대기하는 유효한 포트 번호로 0을 수락 한 다음 수신중인 실제 포트를 알려줍니다. 그러나 합리적인 API는 많지 않습니다. 많은 프로그램이 특별히 0 포트가 통과했는지 테스트하고 거부합니다 ( ssh -D 127.0.0.0:0 ...? 아니요!). 정말 실망 스럽습니다. 우리가 사용할 수 있도록 많은 라이브러리 / 프로그램을 패치해야했습니다.
Joker_vD

2
사용하는 경우 @vorburger 어떤 포트를주의를 닫습니다주의해야한다. new ServerSocket(0)이 점에서 다르지 않습니다. 이것에 대한 첫 번째 링크에는 아무것도 없습니다. 두 번째 링크는 실습이 좋지 않습니다. 일단 구성한 후에 ServerSocket사용 하지 말고 닫지 말고 동일한 포트 번호를 재사용하십시오. 이 모든 것은 시간 낭비이며 타이밍 창 문제에 취약합니다.
Lorne의 후작

57

ServerSocket의 생성자에 포트 번호로 0을 전달하면 포트가 할당됩니다.


예, 가장 우아한 솔루션이라고 생각하지만 어떤 이유로 든 내 경우에는 작동하지 않습니다. 그러나 나는 여전히 정확히 무엇이 잘못되었는지 알아야합니다.
로마

1
@Roman : 왜 작동하지 않습니까? 이것을 포함하도록 질문을 업데이트하십시오 (또는 사람들이 계속 제안 함).이 솔루션이 왜 실패하는지 설명하십시오.
FrustratedWithFormsDesigner

2
클라이언트에서이 포트를 어떻게 찾습니까? ;)
ed22

34

Java 1.7부터 다음과 같은 try-with-resources를 사용할 수 있습니다.

  private Integer findRandomOpenPortOnAllLocalInterfaces() throws IOException {
    try (
        ServerSocket socket = new ServerSocket(0);
    ) {
      return socket.getLocalPort();

    }
  }

특정 인터페이스에서 열린 포트를 찾아야하는 경우 대체 생성자에 대해서는 ServerSocket 설명서를 확인하십시오 .

경고 : 이 방법으로 반환 된 포트 번호를 사용하는 코드는 경쟁 조건에 따라 달라질 수 있습니다. ServerSocket 인스턴스를 닫은 직후 다른 프로세스 / 스레드가 동일한 포트에 바인딩 될 수 있습니다.


1
설정하지 않으면 작동하지 않을 수 있습니다 SO_REUSEADDR. 그리고 경쟁 조건이 있지만 그것을 고치기는 어렵습니다.
David Ehrmann 2016 년

그 동안 동일한 포트 번호로 다른 ServerSocket 포트 번호를 사용하여 다른 포트 를 열려고하면 작동하지 않을 수 있습니다. ServerSocket닫는 대신 실제 를 반환하지 않는 이유는 여전히 미스터리입니다.
Lorne의 후작

5
@EJP 때때로 써드 파티 코드는 소켓 자체가 아닌 포트를 허용합니다.
캡틴 맨

@CaptainMan 물론이지만,이 경우 포트는 반드시 사전 할당 된 것으로 간주됩니다. 이름 지정 서비스 또는 브로드 캐스트 또는 멀티 캐스트와 같은 다른 메커니즘을 통해 동적으로 할당 된 포트를 클라이언트에 제공해야합니다. 여기에있는 모든 질문이 잘못되었습니다.
Lorne의 후작

@ user207421 포트 ServerSocket대신에 대신 타사 코드를 수락하도록 변경할 수 없습니다 int.
Captain Man

30

Wikipedia 에 따르면 '잘 알려진'포트가 필요하지 않은 경우 포트 4915265535사용해야합니다.

AFAIK 포트 사용 여부를 확인하는 유일한 방법은 포트를 열려고 시도하는 것입니다.


6
+1. Wikipedia가 항상 완전한 진실 / 사실의 출처는 아니기 때문에 Wikipedia 페이지에 대한 참조는 "IANA (Internet Assigned Numbers Authority)"의 "[서비스 이름 및 전송 프로토콜 포트 번호" Registry ( iana.org/assignments/service-names-port-numbers/… "페이지, RFC 6335- 섹션 6 (즉,이 경우"솔리드 "참조!)을 기반으로합니다.
OzgurH

25

범위 내 에서 필요한 경우 :

public int nextFreePort(int from, int to) {
    int port = randPort(from, to);
    while (true) {
        if (isLocalPortFree(port)) {
            return port;
        } else {
            port = ThreadLocalRandom.current().nextInt(from, to);
        }
    }
}

private boolean isLocalPortFree(int port) {
    try {
        new ServerSocket(port).close();
        return true;
    } catch (IOException e) {
        return false;
    }
}

포트를 확인하고 바인딩을 해제하는 방법이 궁금했습니다. 감사합니다 SergeyB!
Vlad Ilie

5
[from, to) 범위의 모든 포트가 사용중인 경우이 코드는 무한대로 반복됩니다 (또는 적어도 해당 포트 중 하나가 해제 될 때까지). 범위 내에서 임의의 포트를 선택하지 않고 순차적 스캔을 수행하는 경우이 가능성을 피할 수 있습니다 (사용 가능한 포트를 찾지 않고 범위의 끝에 도달하면 예외가 발생 함). 실제로 무작위로 포트를 선택해야하는 경우, 지금까지 시도한 포트를 추적하고 해당 세트의 크기가-에서 같을 때 오류를 발생시키는 세트가 필요합니다.
Simon Kissane

포트 0은 상당히 단순하며 ServerSockets성공 사례에서 두 개 를 만들 필요 가 없으며이 코드의 타이밍 창 문제로 고통받지 않습니다.
Lorne의 후작


11

Eclipse SDK에는 원하는 소켓 소켓 클래스가 포함되어 있습니다 . git 소스 코드를 살펴볼 수 있습니다 .


2
Eclipse의 코드를 살펴보면 Graham Edgecombe의 답변과 동일한 작업을 수행합니다.
KevinL


6

이것은 Java 6에서 나를 위해 작동합니다.

    ServerSocket serverSocket = new ServerSocket(0);
    System.out.println("listening on port " + serverSocket.getLocalPort());

6

나는 최근에 테스트를 염두에두고 작은 라이브러리를 출시했습니다. Maven 의존성은 다음과 같습니다

<dependency>
    <groupId>me.alexpanov</groupId>
    <artifactId>free-port-finder</artifactId>
    <version>1.0</version>
</dependency>

설치가 완료되면 다음을 통해 무료 포트 번호를 얻을 수 있습니다.

int port = FreePortFinder.findFreeLocalPort();

4

서버가 시작되면 해당 소켓이 사용되지 않은 것입니다.

편집하다

다음과 같은 것 :

ServerSocket s = null ;

try { 
    s = new ServerSocket( 0 ); 
} catch( IOException ioe ){
   for( int i = START; i < END ; i++ ) try {
        s = new ServerSocket( i );
    } catch( IOException ioe ){}
}
// At this point if s is null we are helpless
if( s == null ) {
    throw new IOException(
       Strings.format("Unable to open server in port range(%d-%d)",START,END));
}

누가 당신을 투표했는지 모르겠지만, 나는 당신을 다시 투표했습니다. ServerSocket 설정을 시도하기 위해 재귀 함수를 설정할 수 있으며 IOException (또는 그 무엇이든)이 발생하면 성공적으로 포트를 얻을 때까지 다시 시도하십시오.
jonescb

포트가 사용 가능한지 확인한 다음이 포트의 청취를 시작하는 것이 좋습니다. 무언가를 시작한 다음 문제가 있음을 알아 낸 다음 이러한 문제를 해결하려고 시도하는 것이 우아하지 않은 것 같습니다.
로마

2
@Roman은 포트가 사용 가능한지 알 수있는 방법이 없다는 점을 제외하면 더 좋을 것입니다. new ServerSocket(0)대안이 효과가 없다면 이것입니다. 내 제안을 사용할 가능성의 85 %가 있다고 생각합니다.
OscarRyz

이 코드는 계속 열려 있고 누출 ServerSockets되며 성공한 마지막 코드 만 유지합니다 . break진술 이 필요합니다 .
Lorne의 후작

4

를 사용하여 자체 서버를 만들려면 사용 ServerSocket가능한 포트를 선택하십시오.

  ServerSocket serverSocket = new ServerSocket(0);
  int port = serverSocket.getLocalPort();

다른 서버 구현은 일반적으로 유사한 지원을 갖습니다. 예를 들어 Jetty 는 명시 적으로 설정하지 않으면 사용 가능한 포트를 선택합니다.

  Server server = new Server();
  ServerConnector connector = new ServerConnector(server);
  // don't call: connector.setPort(port);
  server.addConnector(connector);
  server.start();
  int port = connector.getLocalPort();

3

그것은 당신에게별로 도움이되지는 않지만 내 (우분투) 컴퓨터에는 적어도 일부 앱에서 사용 / 예약 된 포트가 제공되는 / etc / services 파일이 있습니다. 이러한 앱의 표준 포트입니다.

이러한 응용 프로그램이 실행 중임을 보장하지는 않으며, 이러한 앱이 사용하는 기본 포트만 가능하므로 가능하면 사용하지 않아야합니다.

UDP의 절반과 TCP의 절반 인 500 개가 넘는 포트가 정의되어 있습니다.

파일은 IANA의 정보를 사용하여 작성됩니다 ( IANA 할당 포트 번호 참조) .


nmap의 일부로 제공되는 유사한 (그리고 더 완전한 IIRC) 목록이 있습니다. +1
rmeador

3

Spring을 사용하는 경우 Michail Nikolaev 가 제공하는 답변 이 가장 간단하고 깨끗하며 IMO를 상향 조정해야합니다. 편의상 Springframwework SocketUtils .findAvailableTcpPort () 메소드 를 사용하여 인라인 예제를 추가 하겠습니다 .

int randomAvailablePort = SocketUtils.findAvailableTcpPort();

한 줄만 있으면 쉽습니다. :). 물론 Utils 클래스는 다른 많은 흥미로운 방법을 제공합니다. 문서를 살펴 보는 것이 좋습니다.


1

'ServerSocket'클래스를 사용하면 주어진 포트가 사용 중인지 또는 사용 가능한지 식별 할 수 있습니다. ServerSocket은 정수 (포트 번호)를 인수로 사용하여 포트에서 서버 소켓을 초기화하는 생성자를 제공합니다. ServerSocket에서 IO 예외가 발생하면이 포트가 이미 사용중인 것으로 가정 할 수 있습니다.

다음 스 니펫은 사용 가능한 모든 포트를 가져 오는 데 사용됩니다.

for (int port = 1; port < 65535; port++) {
         try {
                  ServerSocket socket = new ServerSocket(port);
                  socket.close();
                  availablePorts.add(port);
         } catch (IOException e) {

         }
}

참조 링크 .


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.