简体   繁体   English

如何找到可用端口?

[英]How to find an available port?

I want to start a server which listen to a port.我想启动一个监听端口的服务器。 I can specify port explicitly and it works.我可以明确指定端口并且它有效。 But I would like to find a port in an automatic way.但我想以自动方式找到一个端口。 In this respect I have two questions.在这方面我有两个问题。

  1. In which range of port numbers should I search for?我应该在哪个端口号范围内搜索? (I used ports 12345, 12346, and 12347 and it was fine). (我使用了端口 12345、12346 和 12347,没问题)。

  2. How can I find out if a given port is not occupied by another software?如何确定给定端口是否未被其他软件占用?

If you don't mind the port used, specify a port of 0 to the ServerSocket constructor and it will listen on any free port.如果您不介意使用的端口,请为ServerSocket 构造函数指定端口 0,它将侦听任何空闲端口。

ServerSocket s = new ServerSocket(0);
System.out.println("listening on port: " + s.getLocalPort());

If you want to use a specific set of ports, then the easiest way is probably to iterate through them until one works.如果您想使用一组特定的端口,那么最简单的方法可能是遍历它们,直到它们起作用为止。 Something like this:像这样的东西:

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");
}

Could be used like so:可以这样使用:

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");
}

如果您将 0 作为端口号传递给 ServerSocket 的构造函数,它将为您分配一个端口。

Starting from Java 1.7 you can use try-with-resources like this:从 Java 1.7 开始,您可以像这样使用 try-with-resources:

  private Integer findRandomOpenPortOnAllLocalInterfaces() throws IOException {
    try (
        ServerSocket socket = new ServerSocket(0);
    ) {
      return socket.getLocalPort();

    }
  }

If you need to find an open port on a specific interface check ServerSocket documentation for alternative constructors.如果您需要在特定接口上查找开放端口,请查看ServerSocket文档以获取替代构造函数。

Warning: Any code using the port number returned by this method is subject to a race condition - a different process / thread may bind to the same port immediately after we close the ServerSocket instance.警告:使用此方法返回的端口号的任何代码都会受到竞争条件的影响 - 在我们关闭 ServerSocket 实例后,不同的进程/线程可能会立即绑定到同一端口。

According to Wikipedia , you should use ports 49152 to 65535 if you don't need a 'well known' port.根据Wikipedia ,如果您不需要“众所周知”的端口,您应该使用端口4915265535

AFAIK the only way to determine wheter a port is in use is to try to open it. AFAIK 确定端口是否正在使用的唯一方法是尝试打开它。

If you need in range use:如果您需要在范围内使用:

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;
    }
}

The Eclipse SDK contains a class SocketUtil , that does what you want. Eclipse SDK 包含一个类SocketUtil ,它可以满足您的需求。 You may have a look into the git source code .您可以查看 git 源代码

See ServerSocket :请参阅ServerSocket

Creates a server socket, bound to the specified port.创建一个绑定到指定端口的服务器套接字。 A port of 0 creates a socket on any free port.端口 0 在任何空闲端口上创建套接字。

This works for me on Java 6这在 Java 6 上对我有用

    ServerSocket serverSocket = new ServerSocket(0);
    System.out.println("listening on port " + serverSocket.getLocalPort());

I have recently released a tiny library for doing just that with tests in mind.我最近发布了一个小库,用于在考虑测试的情况下做到这一点。 Maven dependency is: Maven 依赖项是:

<dependency>
    <groupId>me.alexpanov</groupId>
    <artifactId>free-port-finder</artifactId>
    <version>1.0</version>
</dependency>

Once installed, free port numbers can be obtained via:安装后,可以通过以下方式获取免费端口号:

int port = FreePortFinder.findFreeLocalPort();

If you want to create your own server using a ServerSocket , you can just have it pick a free port for you:如果你想使用ServerSocket创建你自己的服务器,你可以让它为你选择一个免费端口:

  ServerSocket serverSocket = new ServerSocket(0);
  int port = serverSocket.getLocalPort();

Other server implementations typically have similar support.其他服务器实现通常有类似的支持。 Jetty for example picks a free port unless you explicitly set it:例如,除非您明确设置,否则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();

If your server starts up, then that socket was not used.如果您的服务器启动,则未使用该套接字。

EDIT编辑

Something like:就像是:

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));
}

It may not help you much, but on my (Ubuntu) machine I have a file /etc/services in which at least the ports used/reserved by some of the apps are given.它可能对您没有多大帮助,但在我的(Ubuntu)机器上,我有一个文件 /etc/services,其中至少提供了一些应用程序使用/保留的端口。 These are the standard ports for those apps.这些是这些应用程序的标准端口。

No guarantees that these are running, just the default ports these apps use (so you should not use them if possible).不能保证这些正在运行,只是这些应用程序使用的默认端口(因此如果可能,您不应该使用它们)。

There are slightly more than 500 ports defined, about half UDP and half TCP.定义的端口略多于 500 个,大约一半是 UDP,一半是 TCP。

The files are made using information by IANA, see IANA Assigned port numbers .这些文件是使用 IANA 提供的信息制作的,请参阅IANA 分配的端口号

If you are using Spring, the answer provided by Michail Nikolaev is the simplest and cleanest one, and IMO should be upvoted.如果您使用的是 Spring,那么Michail Nikolaev提供的答案是最简单、最干净的答案,并且 IMO 应该得到支持。 Just for convenience purposes, I'll add an inline example using the Springframwework SocketUtils .findAvailableTcpPort() method:为方便起见,我将使用Springframwework SocketUtils .findAvailableTcpPort()方法添加一个内联示例:

int randomAvailablePort = SocketUtils.findAvailableTcpPort();

It's as easy as that, just one line :).就这么简单,就一行 :)。 Of course, the Utils class offer many other interesting methods, I suggest having a look at the docs.当然,Utils 类提供了许多其他有趣的方法,我建议查看文档。

If you are using the Spring Framework, the most straightforward way to do this is:如果您使用的是 Spring 框架,最直接的方法是:

private Integer laancNotifyPort = SocketUtils.findAvailableTcpPort();

You can also set an acceptable range, and it will search in this range:你也可以设置一个可接受的范围,它会在这个范围内搜索:

private Integer laancNotifyPort = SocketUtils.findAvailableTcpPort(9090, 10090);

This is a convenience method that abstracts away the complexity but internally is similar to a lot of the other answers on this thread.这是一种抽象出复杂性的便捷方法,但在内部类似于此线程上的许多其他答案。

Using 'ServerSocket' class we can identify whether given port is in use or free.使用“ServerSocket”类,我们可以识别给定的端口是在使用中还是空闲。 ServerSocket provides a constructor that take an integer (which is port number) as argument and initialise server socket on the port. ServerSocket 提供了一个构造函数,它接受一个整数(即端口号)作为参数并在端口上初始化服务器套接字。 If ServerSocket throws any IO Exception, then we can assume this port is already in use.如果 ServerSocket 抛出任何 IO 异常,那么我们可以假设该端口已被使用。

Following snippet is used to get all available ports.以下代码段用于获取所有可用端口。

for (int port = 1; port < 65535; port++) {
         try {
                  ServerSocket socket = new ServerSocket(port);
                  socket.close();
                  availablePorts.add(port);
         } catch (IOException e) {

         }
}

Reference link .参考链接

You can ask the ServerSocket to find a port for you then close it:你可以要求 ServerSocket 为你找到一个端口然后关闭它:

private int getFreePort() {
        var freePort = 0;
        try (ServerSocket s = new ServerSocket(0)) {
            freePort = s.getLocalPort();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return freePort;
    }

There are a lot of answers here where ServerSocket is used.使用ServerSocket的地方这里有很多答案。 I checked Micronauts implementation and they instead try to connect a client socket to the port locally and if that fails they say the port is open.我检查了 Micronauts 的实现,他们改为尝试将客户端套接字连接到本地端口,如果失败,他们会说端口已打开。 That to me has the advantage that they do not risk using the port within the test.对我来说,这样做的好处是他们不会冒险在测试中使用端口。

Their code looks like this:他们的代码如下所示:

    public static boolean isTcpPortAvailable(int currentPort) {
        try (Socket socket = new Socket()) {
            socket.connect(new InetSocketAddress(InetAddress.getLocalHost(), currentPort), 20);
            return false;
        } catch (Throwable e) {
            return true;
        }
    }

See here for reference: https://github.com/micronaut-projects/micronaut-core/blob/3.4.x/core/src/main/java/io/micronaut/core/io/socket/SocketUtils.java参考这里: https://github.com/micronaut-projects/micronaut-core/blob/3.4.x/core/src/main/java/io/micronaut/core/io/socket/SocketUtils.java

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM