我想启动一个监听端口的服务器。我可以明确指定端口,它可以工作。但我想以自动方式找到一个端口。在这方面,我有两个问题。
我应该在哪个端口号范围内搜索? (我使用了端口12345,12346和12347,很好)。
如何判断某个端口是否未被其他软件占用?
答案 0 :(得分:248)
如果您不介意使用的端口,请为ServerSocket constructor指定一个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");
}
答案 1 :(得分:49)
如果将0作为端口号传递给ServerSocket的构造函数,它将为您分配一个端口。
答案 2 :(得分:29)
从Java 1.7开始,您可以像这样使用try-with-resources:
private Integer findRandomOpenPortOnAllLocalInterfaces() throws IOException {
try (
ServerSocket socket = new ServerSocket(0);
) {
return socket.getLocalPort();
}
}
如果您需要在特定接口上找到一个开放端口,请检查ServerSocket文档以获取替代构造函数。
警告:使用此方法返回的端口号的任何代码都会受到竞争条件的影响 - 在关闭ServerSocket实例后,不同的进程/线程可能会立即绑定到同一个端口。
答案 3 :(得分:23)
根据Wikipedia,如果您不需要“众所周知”的端口,则应将端口49152
用于65535
。
AFAIK确定端口正在使用的唯一方法是尝试打开它。
答案 4 :(得分:20)
如果您需要 范围 ,请使用:
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;
}
}
答案 5 :(得分:19)
如果您使用Spring,可以尝试http://docs.spring.io/spring/docs/4.0.5.RELEASE/javadoc-api/org/springframework/util/SocketUtils.html#findAvailableTcpPort--
答案 6 :(得分:10)
Eclipse SDK包含一个类SocketUtil,可以满足您的需求。您可以查看git source code。
答案 7 :(得分:6)
请参阅http://java.sun.com/j2se/1.4.2/docs/api/java/net/ServerSocket.html#ServerSocket%28int%29
创建绑定到指定端口的服务器套接字。端口0在任何空闲端口上创建套接字。
答案 8 :(得分:6)
这适用于Java 6
ServerSocket serverSocket = new ServerSocket(0);
System.out.println("listening on port " + serverSocket.getLocalPort());
答案 9 :(得分:4)
如果您想使用ServerSocket
创建自己的服务器,可以让它为您选择一个免费端口:
ServerSocket serverSocket = new ServerSocket(0);
int port = serverSocket.getLocalPort();
其他服务器实现通常具有类似的支持。 Jetty 例如选择一个空闲端口,除非您明确设置它:
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
// don't call: connector.setPort(port);
server.addConnector(connector);
server.start();
int port = connector.getLocalPort();
答案 10 :(得分:4)
我最近发布了一个小型库,用于考虑测试。 Maven依赖是:
<dependency>
<groupId>me.alexpanov</groupId>
<artifactId>free-port-finder</artifactId>
<version>1.0</version>
</dependency>
安装后,可通过以下方式获取空闲端口号:
int port = FreePortFinder.findFreeLocalPort();
答案 11 :(得分:3)
如果您的服务器启动,则不使用该套接字。
修改强>
类似的东西:
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));
}
答案 12 :(得分:3)
它可能对你没什么帮助,但在我的(Ubuntu)机器上我有一个文件/ etc / services,其中至少给出了一些应用程序使用/保留的端口。这些是这些应用程序的标准端口。
无法保证这些应用程序正在运行,只是这些应用程序使用的默认端口(因此,如果可能,请不要使用它们)。
定义的端口略多于500个,大约有一半UDP和一半TCP。
这些文件是使用IANA的信息制作的,请参阅IANA Assigned port numbers。
答案 13 :(得分:1)
如果您使用的是Spring,则 Michail Nikolaev 提供的答案是最简单,最简洁的答案,应该赞成IMO。 为了方便起见,我将使用Springframwework SocketUtils。findAvailableTcpPort()方法添加一个内联示例:
int randomAvailablePort = SocketUtils.findAvailableTcpPort();
就这么简单,只需一行:)。当然,Utils类提供了许多其他有趣的方法,建议您看一下文档。
答案 14 :(得分:1)
使用“ ServerSocket”类,我们可以确定给定端口是正在使用还是空闲。 ServerSocket提供了一个构造函数,该构造函数采用整数(即端口号)作为 参数并初始化端口上的服务器套接字。如果ServerSocket抛出任何IO异常,那么我们可以假定此端口已在使用中。
以下代码段用于获取所有可用端口。
for (int port = 1; port < 65535; port++) {
try {
ServerSocket socket = new ServerSocket(port);
socket.close();
availablePorts.add(port);
} catch (IOException e) {
}
}
参考link。
答案 15 :(得分:0)
如果您使用的是Spring Framework,最简单的方法是:
private Integer laancNotifyPort = SocketUtils.findAvailableTcpPort();
您还可以设置一个可接受的范围,它将在该范围内搜索:
private Integer laancNotifyPort = SocketUtils.findAvailableTcpPort(9090, 10090);
这是一种方便的方法,可以抽象出复杂性,但是内部类似于该线程上的许多其他答案。