找到两个空闲的 tcp 端口
Posted
技术标签:
【中文标题】找到两个空闲的 tcp 端口【英文标题】:Finding two free tcp ports 【发布时间】:2011-03-17 00:01:55 【问题描述】:我知道下面的代码可以(可能不是很有效)在 Java 中找到一个空闲的 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 - for example 中有一些相关问题)。
我不明白为什么(或是否)两次连续调用此方法可以保证返回两个不同的端口。例如,这是假定为here(搜索对findFreePort
方法的调用)。
这是正确的吗?
【问题讨论】:
如果有相关问题,您应该引用它们并链接到它们。 由于 SO_WAIT 而没有重新分配它,这是一种旨在避免仍在传输中的数据包会被另一个进程接收的机制。默认情况下,关闭一个 TCP 端口,在接下来的 2 分钟内不会重新分配它以允许这些滞留数据包刷新。 在我看来,这种行为可能很常见,但只是依赖于实现,不是吗? tcpipguide.com/free/…technet.microsoft.com/en-us/library/cc759700(v=ws.10).aspx 我不知道这是否是一个标准,但绝对是一个很好的安全/隐私措施。 【参考方案1】:在 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;
【讨论】:
应该注意的是,即使这个解决方案(和 Noel M 的)也不是 100% 万无一失的,存在潜在的竞争条件。在这个方法调用之后,调用者最终会尝试使用那些可用的端口。但也有可能同时其他进程打开了它。【参考方案2】:获取两个不同端口号的一种方法:
ServerSocket socket1 = new ServerSocket(0);
port1 = socket1.getLocalPort();
ServerSocket socket2 = new ServerSocket(0);
port2 = socket2.getLocalPort();
socket1.close();
socket2.close();
【讨论】:
我想你的意思是socket1.getLocalPort()
和socket2.getLocalPort()
【参考方案3】:
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 的连续调用不会重用该端口,从而保证两个不同的端口。
【讨论】:
但是findFreePort
打开socket并立即关闭它,所以理论上又是可用的。
在代码中,端口被分配,但是“close()”方法取消分配这个端口。然后,它可以被重用(例如,由另一个 ServerSocket)。所以,我认为对该方法的另一个调用可能会给出相同的端口号。【参考方案4】:
它与操作系统所能达到的一样高效。但是,之后立即关闭 ServerSocket 是没有意义的,因为该端口不再保留并且可以分配给其他东西。本练习的唯一目的是创建一个 ServerSocket,因此只需创建它即可。
【讨论】:
【参考方案5】:这是我用来查找多个空闲端口的类。它提供了在某些复杂逻辑流中分配单个端口的灵活性(即,当您需要的端口数量可能不是一个简单的数字,而是取决于复杂的逻辑时)。它仍然保证您请求的所有端口都是免费且唯一的(只要您使用该类的相同实例来获取所有端口)。
所以使用这个类的方法是创建一个实例。执行您的代码以执行您想要为使用该实例分配端口的任何操作。然后,一旦你绑定了所有端口,你就可以处理这个实例并在下次使用一个新的。
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;
【讨论】:
findFreePort() 在哪里;方法。 @克里斯 就在那里,PortFinder 类的第一个成员。也许我把它放在字段声明之前的不寻常顺序弄糊涂了。以上是关于找到两个空闲的 tcp 端口的主要内容,如果未能解决你的问题,请参考以下文章
使用 Twisted python 是不是有一种机制可以找到类似于 socket.open 的空闲端口?
使用Twisted python,有一种机制可以找到类似于socket.open的空闲端口。