Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find free port in Java

I need to find a free port in a Java Application. Why doesn't the below code work? It always returns 0.

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

Java doc of new InetSocketAddress() says:

Creates a socket address where the IP address is the wildcard address and the port number a specified value.

A valid port value is between 0 and 65535. A port number of zero will let the system pick up an ephemeral port in a bind operation.

like image 235
vineeth kumar Avatar asked Jun 29 '18 09:06

vineeth kumar


1 Answers

Actually you output the port member that you specified in the constructor. So 0 is expected.
The javadoc states that the port will let the system pick up an ephemeral port for a binding operation. It doesn't tell that the port number will be valued with the ephemeral port directly in the InetSocketAddress instance. Actually you don't execute a binding operation with this InetSocketAddress instance.
In clear you didn't open/create a socket channel to communicate with this instance. So you cannot notice the result of the port.

For example this binds the a ServerSocket to a InetSocketAddress :

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

Here is a more complete example illustrating how things work :

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

    }
}

Output :

randomSocketAddress port before any binding : 0

local port after first binding : 65110

local port after second binding : 65111

randomSocketAddress port after all bindings : 0

You can see that the InetSocketAddress object keeps always 0 as port value while the ServerSocket objects benefit from a picked up ephemeral port.

like image 58
davidxxx Avatar answered Sep 17 '22 23:09

davidxxx