如何找到可用的端口?

时间:2010-04-20 13:16:09

标签: java networking sockets port

我想启动一个监听端口的服务器。我可以明确指定端口,它可以工作。但我想以自动方式找到一个端口。在这方面,我有两个问题。

  1. 我应该在哪个端口号范围内搜索? (我使用了端口12345,12346和12347,很好)。

  2. 如何判断某个端口是否未被其他软件占用?

16 个答案:

答案 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)

答案 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);

这是一种方便的方法,可以抽象出复杂性,但是内部类似于该线程上的许多其他答案。