我想启动一个侦听端口的服务器。我可以显式地指定端口,它工作。但我想以自动的方式找到一个端口。在这方面,我有两个问题。
我应该在哪个范围内搜索端口号?(我使用的端口是12345、12346和12347,没有问题)。 我如何知道给定的端口是否被其他软件占用?
我想启动一个侦听端口的服务器。我可以显式地指定端口,它工作。但我想以自动的方式找到一个端口。在这方面,我有两个问题。
我应该在哪个范围内搜索端口号?(我使用的端口是12345、12346和12347,没有问题)。 我如何知道给定的端口是否被其他软件占用?
当前回答
这可能对你没有太大帮助,但在我的(Ubuntu)机器上,我有一个文件/etc/services,其中至少给出了一些应用程序使用/保留的端口。这些是这些应用的标准端口。
不能保证这些端口正在运行,只是这些应用程序使用的默认端口(所以如果可能的话,你不应该使用它们)。
定义了500多个端口,大约一半是UDP,一半是TCP。
这些文件是使用IANA的信息制作的,请参见IANA指定的端口号。
其他回答
如果您正在使用Spring,那么由Michail Nikolaev提供的答案是最简单、最干净的,IMO应该给予好评。 为了方便起见,我将使用springframework SocketUtils.findAvailableTcpPort()方法添加一个内联示例:
int randomAvailablePort = SocketUtils.findAvailableTcpPort();
就这么简单,只有一行:)。当然,Utils类提供了许多其他有趣的方法,我建议看看文档。
如果服务器启动,则该套接字未被使用。
EDIT
喜欢的东西:
ServerSocket s = null ;
try {
s = new ServerSocket( 0 );
} catch( IOException ioe ){
for( int i = START; i < END ; i++ ) try {
s = new ServerSocket( i );
} catch( IOException ioe ){}
}
// At this point if s is null we are helpless
if( s == null ) {
throw new IOException(
Strings.format("Unable to open server in port range(%d-%d)",START,END));
}
从Java 1.7开始,你可以像这样使用try-with-resources:
private Integer findRandomOpenPortOnAllLocalInterfaces() throws IOException {
try (
ServerSocket socket = new ServerSocket(0);
) {
return socket.getLocalPort();
}
}
如果需要在特定接口上找到一个开放端口,请检查ServerSocket文档以获得替代构造函数。
警告:任何使用此方法返回的端口号的代码都会受到竞态条件的影响——在关闭ServerSocket实例后,不同的进程/线程可能会立即绑定到相同的端口。
如果您将0作为端口号传递给ServerSocket的构造函数,它将为您分配一个端口。
如果您需要在范围内使用:
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;
}
}