Нахождение двух свободных портов TCP - PullRequest
6 голосов
/ 16 июля 2010

Я понимаю, что следующий код может (возможно, не очень эффективно) найти свободный порт TCP в Java:

  public static int findFreePort() {
    int port;
    try {
      ServerSocket socket= new ServerSocket(0);
      port = socket.getLocalPort();
      socket.close(); 
    } catch (Exception e) { port = -1; }
    return port;    
  } 

(Есть некоторые связанные вопросы здесь в SO - для пример ).

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

Это правильно?

Ответы [ 5 ]

5 голосов
/ 16 июля 2010

В спецификации Javadoc я не вижу ни одной строки, говорящей о том, что два последовательных вызова гарантированно возвращают два разных порта ...

Поскольку ServerSocket закрыт, второй вызов может дать тот же порт. Статистически, это непросто, но не невозможно, я думаю.

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

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

public int[] getFreePorts(int portNumber) throws IOException {
    int[] result = new int[portNumber];
    List<ServerSocket> servers = new ArrayList<ServerSocket>(portNumber);
    ServerSocket tempServer = null;

    for (int i=0; i<portNumber; i++) {
        try {
            tempServer = new ServerSocket(0);
            servers.add(tempServer);
            result[i] = tempServer.getLocalPort();
        } finally {
            for (ServerSocket server : servers) {
                try {
                    server.close();
                } catch (IOException e) {
                    // Continue closing servers.
                }
            }
        }
    }
    return result;
}
2 голосов
/ 16 июля 2010

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

  ServerSocket socket1 = new ServerSocket(0);
  port1 = socket1.getLocalPort();
  ServerSocket socket2 = new ServerSocket(0);
  port2 = socket2.getLocalPort();

  socket1.close();
  socket2.close(); 
0 голосов
/ 17 сентября 2013

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

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

public class PortFinder {

/**
 * If you only need the one port you can use this. No need to instantiate the class
 */
public static int findFreePort() throws IOException {
    ServerSocket socket = new ServerSocket(0);
    try {
        return socket.getLocalPort();
    } finally {
        try {
            socket.close();
        } catch (IOException e) {
        }
    }
}

private HashSet<Integer> used = new HashSet<Integer>();

/**
 * Finds a port that is currently free and is guaranteed to be different from any of the
 * port numbers previously returned by this PortFinder instance.
 */
public synchronized int findUniqueFreePort() throws IOException {
    int port;
    do {
        port = findFreePort();
    } while (used.contains(port));
    used.add(port);
    return port;
}

}
0 голосов
/ 17 июля 2010

Это настолько эффективно, насколько операционная система может это сделать.Однако закрытие ServerSocket сразу после этого бессмысленно, так как этот порт больше не зарезервирован и может быть выделен для чего-то другого.Единственная цель этого упражнения - создать ServerSocket, поэтому просто создайте его.

0 голосов
/ 16 июля 2010

Исходный код для ServerSocket находится здесь: http://kickjava.com/src/java/net/ServerSocket.java.htm

Я не совсем понимаю, как он определяет, свободен порт или нет, но:

@param port the port number, or <code>0</code> to use any
free port.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...