【问题标题】:Find free port in Java在 Java 中查找空闲端口
【发布时间】:2018-12-08 11:44:06
【问题描述】:

我需要在 Java 应用程序中找到一个空闲端口。为什么下面的代码不起作用?它总是返回 0。

public int findFreePort() {
    int portNumber = new InetSocketAddress(0).getPort();
    return portNumber;
}

new InetSocketAddress() 的 Java 文档说:

创建一个套接字地址,其中 IP 地址是通配符地址,端口号是指定值。

有效的端口值介于 0 和 65535 之间。端口号为零将使系统在绑定操作中选择一个临时端口。

【问题讨论】:

  • “在绑定操作中”。你还没有绑定。
  • 要获得空闲端口,您必须尝试绑定到端口 0。

标签: java port ip-address javadoc inet-socket


【解决方案1】:

实际上你输出的是你在构造函数中指定的端口成员。所以0是预期的。
javadoc 声明该端口将让系统为绑定操作选择一个临时端口。 它并没有说明端口号将直接在 InetSocketAddress 实例中使用临时端口进行赋值。 实际上,您不会使用此 InetSocketAddress 实例执行绑定操作。
很明显,您没有打开/创建套接字通道来与此实例进行通信。 所以你不能注意到端口的结果。

例如,这会将ServerSocket 绑定到InetSocketAddress

ServerSocket ss = new ServerSocket(..);
ss.bind(new InetSocketAddress(0));

这里有一个更完整的例子来说明事情是如何工作的:

public class InetSockerAddressWithEphemeralPortMain {

    public static void main(String[] args) throws InterruptedException, IOException {
        InetSocketAddress randomSocketAddressFirst = new InetSocketAddress(0);

        try (ServerSocket ssOne = new ServerSocket()) {
            System.out.println("randomSocketAddress port before any binding : " + randomSocketAddressFirst.getPort());
            ssOne.bind(randomSocketAddressFirst);
            System.out.println("local port after first binding :" + ssOne.getLocalPort());
        }

        try (ServerSocket ssTwo = new ServerSocket()) {
            ssTwo.bind(randomSocketAddressFirst);
            System.out.println("local port after second binding :" + ssTwo.getLocalPort());
            System.out.println("randomSocketAddress port after all bindings : " + randomSocketAddressFirst.getPort());
        }

    }
}

输出:

任何绑定前的randomSocketAddress端口:0

首次绑定后的本地端口:65110

第二次绑定后的本地端口:65111

所有绑定后的randomSocketAddress端口:0

您可以看到InetSocketAddress 对象始终将0 作为端口值,而ServerSocket 对象受益于拾取的临时端口。

【讨论】:

    【解决方案2】:

    如果您只是想在代码中找到一个可用端口,请执行以下操作:

    private static int findFreePort() {
        int port = 0;
        // For ServerSocket port number 0 means that the port number is automatically allocated.
        try (ServerSocket socket = new ServerSocket(0)) {
            // Disable timeout and reuse address after closing the socket.
            socket.setReuseAddress(true);
            port = socket.getLocalPort();
        } catch (IOException ignored) {}
        if (port > 0) {
            return port;
        }
        throw new RuntimeException("Could not find a free port");
    }
    

    【讨论】:

      猜你喜欢
      • 2011-03-17
      • 1970-01-01
      • 2020-11-21
      • 2016-04-10
      • 2021-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-22
      相关资源
      最近更新 更多