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

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

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

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

Ответ 1

Если вы не против используемого порта, укажите порт 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");
}

Ответ 2

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

Ответ 3

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

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

    }
  }

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

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

Ответ 4

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

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

Ответ 5

Если вам нужен диапазон, используйте:

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

Ответ 7

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

Ответ 9

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

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

Ответ 10

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

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

После установки бесплатные номера портов можно получить через:

int port = FreePortFinder.findFreeLocalPort();

Ответ 11

Если вы хотите создать свой собственный сервер с помощью 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();

Ответ 12

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

ИЗМЕНИТЬ

Что-то вроде:

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

Ответ 13

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

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

Определено несколько более 500 портов, около половины UDP и половина TCP.

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

Ответ 14

Если вы используете Spring, ответ, предоставленный Михаилом Николаевым, является самым простым и чистым, и IMO следует проголосовать без голосования. Просто для удобства я добавлю встроенный пример, используя метод SocketUtils.findAvailableTcpPort() Springframwework:

int randomAvailablePort = SocketUtils.findAvailableTcpPort();

Это так просто, всего одна строчка :). Конечно, класс Utils предлагает много других интересных методов, я предлагаю взглянуть на документы.