2010-07-16 51 views
6

我明白,下面的代码可以(也许不是很有效)找出Java的免费的TCP端口:找到两个免费的TCP端口

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 - forexample) 。

我不明白的是为什么(或者是否)对这个方法的两次连续调用都保证返回两个不同的端口。假定这是例如here(搜索findFreePort方法的呼叫)。

这是正确的吗?对于ServerSocket的

+0

如果有相关的问题,你应该引用它们并链接到它们。 – Freiheit 2010-07-16 14:25:53

+0

@Freiheit:完成 – leonbloy 2010-07-16 14:29:59

+0

由于SO_WAIT,这个机制没有被重新分配,这个机制旨在规避一个仍然在传输中的数据包将被另一个进程接收。默认情况下,关闭TCP端口后,在接下来的2分钟内不会重新分配以允许这些延迟的数据包刷新。 – 2014-09-16 14:53:50

回答

5

在Javadoc规范,我看不出有任何行说两个succesive调用保证返回两个不同的端口...

由于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; 
} 
+0

是的,我刚刚编码几乎完全相同的方法:-) – leonbloy 2010-07-17 14:05:52

+1

应该指出,即使这种解决方案(和诺埃尔M的)不是100%万无一失,有潜在的竞争条件。在此方法调用之后,调用者将最终尝试使用这些可用端口。但在此期间可能会发生一些其他进程打开它的情况。 – leonbloy 2010-07-17 14:14:12

0

源代码是在这里:http://kickjava.com/src/java/net/ServerSocket.java.htm

我不太看到它是如何确定该端口是否空闲,但:

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

所以一旦第一个端口分配,即使是你的应用程序,它不再是免费的。所以连续调用ServerSocket将不会重用该端口,从而保证两个不同的端口。

+0

但'findFreePort'打开套接字并立即关闭它,因此理论上再次可用。 – leonbloy 2010-07-16 14:52:43

+0

在代码中,分配端口,但“close()”方法取消分配此端口。然后,它可以被重用(例如由另一个ServerSocket)。所以,我认为对该方法的另一个调用可能会给出相同的端口号。 – 2010-07-16 14:53:30

2

一种方式来获得两个不同的端口号:

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

    socket1.close(); 
    socket2.close(); 
0

这是一样有效,操作系统可以做到这一点。然而,之后立即关闭ServerSocket是没有意义的,因为该端口不再被保留,并且可以分配给其他内容。这个练习的唯一目的是创建一个ServerSocket,所以就创建它。

0

这是我用来查找多个空闲端口的类。它为在一些复杂逻辑流程中分配单个端口提供了灵活性(即,可能需要的端口数量不是简单的数量,而是取决于复杂的逻辑)。它仍然保证你所要求的所有端口都是免费且唯一的(只要你使用这个类的同一个实例来获得所有的端口)。

所以使用这个类的方法是创建一个实例。执行您的代码以执行您想要为使用该实例分配端口的任何操作。然后,一旦你绑定了所有的端口,你就可以处理这个实例并下次使用新的实例。

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

其中是findFreePort(); 方法。 @Kris – Roster 2015-09-14 11:11:46

+0

它就在那里,PortFinder类的第一个成员。也许我通过把它放在现场声明之前的不寻常的顺序来混淆事物。 – Kris 2015-09-15 21:07:41