Search code examples
javaportip-addressjavadocinet-socket

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.


Solution

  • 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.