Java 查找两个空闲tcp端口
我知道以下代码可以(可能不是很有效)找到Java中的免费TCP端口:Java 查找两个空闲tcp端口,java,sockets,tcp,Java,Sockets,Tcp,我知道以下代码可以(可能不是很有效)找到Java中的免费TCP端口: public static int findFreePort() { int port; try { ServerSocket socket= new ServerSocket(0); port = socket.getLocalPort(); socket.close(); } catch (Exception e) { port = -1; } re
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
方法的调用)
这是否正确?ServerSocket的源代码如下: 我不太清楚它是如何确定端口是否空闲的,但是:
@param port the port number, or <code>0</code> to use any
free port.
因此,一旦分配了第一个端口,即使是分配给您的应用程序,它也不再是免费的。因此,对ServerSocket的连续调用将不会重用该端口,从而保证两个不同的端口。在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;
}
public int[]getFreePorts(int端口号)引发IOException{
int[]结果=新int[portNumber];
列表服务器=新的ArrayList(端口号);
ServerSocket tempServer=null;
对于(int i=0;i获取两个不同端口号的一种方法:
ServerSocket socket1 = new ServerSocket(0);
port1 = socket1.getLocalPort();
ServerSocket socket2 = new ServerSocket(0);
port2 = socket2.getLocalPort();
socket1.close();
socket2.close();
它的效率与操作系统所能做到的一样高。但是,之后立即关闭ServerSocket是毫无意义的,因为该端口不再保留,可以分配给其他端口。此练习的唯一目的是创建一个ServerSocket,所以只需创建它。下面是一个用于查找多个可用端口的类s、 它提供了在某些复杂逻辑流中分配单个端口的灵活性(即,当您需要的端口数量可能不是一个简单的数字,而是取决于复杂逻辑时)。它仍然保证您请求的所有端口都是免费的和唯一的(只要您使用该类的同一实例来获取所有端口)
因此,使用此类的方法是创建一个实例。执行您的代码以执行您想要为使用该实例分配端口的任何操作。然后,绑定所有端口后,您可以处置该实例,并在下次使用新实例
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;
}
}
公共类PortFinder{
/**
*如果你只需要一个端口,你可以使用这个。不需要实例化这个类
*/
公共静态int findFreePort()引发IOException{
ServerSocket=新的ServerSocket(0);
试一试{
返回socket.getLocalPort();
}最后{
试一试{
socket.close();
}捕获(IOE异常){
}
}
}
使用的私有HashSet=新HashSet();
/**
*查找当前可用且保证与任何其他端口不同的端口
*此PortFinder实例以前返回的端口号。
*/
public synchronized int findUniqueFreePort()引发IOException{
国际港口;
做{
端口=findFreePort();
}while(used.contains(port));
已使用。添加(端口);
返回端口;
}
}
如果有相关问题,您应该引用它们并链接到它们。由于SO_WAIT(一种旨在避免另一进程接收仍在传输中的数据包的机制)的原因,它不会重新分配。默认情况下,如果您关闭TCP端口,则在接下来的2分钟内不会重新分配以允许这些延迟数据包刷新。这是对我来说,这种行为可能很常见,但只是依赖于实现,不是吗?我不知道这是否是一个标准,但肯定是一个很好的安全/隐私措施。但是findFreePort
打开套接字并在中间关闭它,因此理论上是可用的。在代码中,端口是分配的,但“close()”是方法不允许此端口。然后,它可以恢复(例如,由另一个ServerSocket)。因此,我认为对该方法的另一次调用可能会给出相同的端口号。应该注意的是,即使是此解决方案(以及Noel M的)不是100%万无一失,存在潜在的争用条件。在调用此方法后,调用方最终将尝试使用这些可用端口。但在此期间,可能会有其他进程打开了它。findFreePort()在哪里;方法。@Krist就在那里,PortFinder类的第一个成员。可能我把它放在字段声明之前的不寻常的顺序搞混了。我想你是说socket1.getLocalPort()
和socket2.getLocalPort()