在Java中找到免费端口

vin*_*mar 7 java port javadoc ip-address inet-socket

我需要在Java应用程序中找到一个自由端口.为什么以下代码不起作用?它总是返回0.

public int findFreePort() {
    int portNumber = new InetSocketAddress(0).getPort();
    return portNumber;
}
Run Code Online (Sandbox Code Playgroud)

Java doc new InetSocketAddress()说:

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

有效端口值介于0和65535之间.端口号为零将使系统在绑定操作中获取临时端口.

dav*_*xxx 8

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

例如,这将a绑定ServerSocketInetSocketAddress :

ServerSocket ss = new ServerSocket(..);
ss.bind(new InetSocketAddress(0));
Run Code Online (Sandbox Code Playgroud)

这是一个更完整的示例,说明了工作原理:

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

    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

任何绑定之前的randomSocketAddress端口:0

第一次绑定后的本地端口:65110

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

所有绑定后的randomSocketAddress端口:0

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