我想启动一个监听端口的服务器。我可以明确指定端口并且它可以工作。但是我希望以自动方式查找可用端口。在这方面,我有两个问题。
应该在哪个端口范围内搜索可用端口号?(我使用了12345、12346和12347端口,它们都可以正常使用)。
如何确定给定的端口是否已被其他软件占用?
我想启动一个监听端口的服务器。我可以明确指定端口并且它可以工作。但是我希望以自动方式查找可用端口。在这方面,我有两个问题。
应该在哪个端口范围内搜索可用端口号?(我使用了12345、12346和12347端口,它们都可以正常使用)。
如何确定给定的端口是否已被其他软件占用?
如果您不介意使用的端口号,可以在ServerSocket构造函数中指定端口0,它将监听任何可用的端口。
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");
}
ssh -D 127.0.0.0:0 ...
?不行!),这真的很令人沮丧。我们不得不修改相当数量的库/程序才能让它们对我们有用。 - Joker_vDnew ServerSocket(0)
并没有什么不同。你的第一个链接中根本没有任何关于这个的内容。你的第二个链接只是展示了一种糟糕的做法。一旦你构建了ServerSocket
,你应该使用它,而不是关闭它并尝试重用相同的端口号。所有这些都是完全浪费时间,同时也容易受到时间窗口问题的影响。 - user207421如果在ServerSocket的构造函数中将端口号设为0,则会自动分配一个端口。
private Integer findRandomOpenPortOnAllLocalInterfaces() throws IOException {
try (
ServerSocket socket = new ServerSocket(0);
) {
return socket.getLocalPort();
}
}
SO_REUSEADDR
,这可能无法正常工作。而且存在竞争条件,但很难修复。 - David EhrmannServerSocket
,则此方法可能无法正常工作,因为该端口号可能已被占用。为什么不直接返回实际的ServerSocket
而不是关闭它仍然是个谜。 - user207421ServerSocket
而不是int
作为端口。 - Captain Man根据维基百科的说法,如果您不需要一个“众所周知”的端口,您应该使用端口49152
到65535
。
据我所知,确定端口是否正在使用的唯一方法是尝试打开它。
如果您需要使用范围,请使用:
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;
}
}
SpringUtils.findAvailableTcpPort()
在幕后做的与其他答案中推荐的完全相同:选择一个端口,然后尝试 new ServerSocket(port)
。 - Alexey BerezkinSocketUtils
类现在已经被弃用,并将在Spring 6.0中被移除。 - pTakTestSocketUtils
在Spring 6中仍然存在,但显然是在spring-test模块中。 - undefined我最近发布了一个小型库,专门用于测试。 Maven 依赖:
<dependency>
<groupId>me.alexpanov</groupId>
<artifactId>free-port-finder</artifactId>
<version>1.0</version>
</dependency>
安装完成后,可以通过以下方式获取免费端口号:
int port = FreePortFinder.findFreeLocalPort();
ServerSocket serverSocket = new ServerSocket(0);
System.out.println("listening on port " + serverSocket.getLocalPort());