Как найти доступный порт? - PullRequest
174 голосов
/ 20 апреля 2010

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

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

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

Ответы [ 14 ]

250 голосов
/ 20 апреля 2010

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

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

29 голосов
/ 30 октября 2014

Начиная с Java 1.7 вы можете использовать try-with-resources, например так:

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

    }
  }

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

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

23 голосов
/ 20 апреля 2010

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

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

20 голосов
/ 15 марта 2016

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

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;
    }
}
19 голосов
/ 07 июля 2014

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

10 голосов
/ 20 апреля 2010

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

6 голосов
/ 22 мая 2010

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

    ServerSocket serverSocket = new ServerSocket(0);
    System.out.println("listening on port " + serverSocket.getLocalPort());
6 голосов
/ 20 апреля 2010

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

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

4 голосов
/ 09 мая 2015

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

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

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

int port = FreePortFinder.findFreeLocalPort();
...