Как найти доступный порт?


Я хочу запустить сервер, который слушает порт. Я могу указать порт явно и это работает. Но я хотел бы найти порт в автоматическом режиме. На этот счет у меня есть два вопроса.

  1. в каком диапазоне номеров портов я должен искать? (Я использовал порты 12345, 12346 и 12347, и это было прекрасно).

  2. Как я могу узнать, если данный порт не занят другим программным обеспечением?

13 164

13 ответов:

Если вы не возражаете против используемого порта, укажите порт 0 для конструктор ServerSocket и он будет слушать на любом свободном порту.

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");
}

Если вы передадите 0 в качестве номера порта конструктору ServerSocket, он выделит для вас порт.

начиная с Java 1.7 вы можете использовать try-with-resources следующим образом:

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

    }
  }

Если вам нужно найти открытый порт на определенном интерфейсе проверьте ServerSocket документация для альтернативных конструкторов.

предупреждение: любой код, использующий номер порта, возвращенный этим методом, подчиняется условию гонки - другой процесс / поток может привязаться к тому же порту сразу после закрытия экземпляра ServerSocket.

по данным Википедия, вы должны использовать порты 49152 до 65535 Если вам не нужен "хорошо известный" порт.

AFAIK единственный способ определить, используется ли порт, - это попытаться открыть его.

Если вам нужно в ряд использование:

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;
    }
}

Если вы используете весну, вы можете попробовать http://docs.spring.io/spring/docs/4.0.5.RELEASE/javadoc-api/org/springframework/util/SocketUtils.html#findAvailableTcpPort--

Eclipse SDK содержит класс SocketUtil, что делает то, что вы хотите. Вы можете заглянуть в git исходный код.

см http://java.sun.com/j2se/1.4.2/docs/api/java/net/ServerSocket.html#ServerSocket%28int%29

создает сокет сервера, привязанный к указанному порту. Порт 0 создает сокет на любом свободном порту.

это работает для меня на Java 6

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

Если вы хотите создать свой собственный сервер с помощью ServerSocket, вы можете просто выбрать свободный порт для вас:

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

другие реализации сервера обычно имеют аналогичную поддержку. причал выбирает Свободный порт, если вы явно установите его:

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

недавно я выпустил крошечную библиотеку для выполнения именно этого с тестами в виду. Зависимость Maven:

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

после установки номера свободных портов можно получить с помощью:

int port = FreePortFinder.findFreeLocalPort();

Это может вам не очень помочь, но на моей машине (Ubuntu) у меня есть файл /etc/services, в котором по крайней мере указаны порты, используемые/зарезервированные некоторыми приложениями. Это стандартные порты для этих приложений.

нет гарантий, что они работают, только порты по умолчанию, которые используют эти приложения (поэтому вы не должны использовать их, если это возможно).

определено чуть более 500 портов, примерно половина UDP и половина TCP.

файлы создаются с использованием информации Яна, смотри IANA присвоены номера портов.

Если ваш сервер запускается, то это гнездо не используется.

EDIT

что-то типа:

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));
}