Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sockets: Discover port availability using Java

Tags:

java

port

sockets

This is the implementation coming from the Apache camel project:

/**
 * Checks to see if a specific port is available.
 *
 * @param port the port to check for availability
 */
public static boolean available(int port) {
    if (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER) {
        throw new IllegalArgumentException("Invalid start port: " + port);
    }

    ServerSocket ss = null;
    DatagramSocket ds = null;
    try {
        ss = new ServerSocket(port);
        ss.setReuseAddress(true);
        ds = new DatagramSocket(port);
        ds.setReuseAddress(true);
        return true;
    } catch (IOException e) {
    } finally {
        if (ds != null) {
            ds.close();
        }

        if (ss != null) {
            try {
                ss.close();
            } catch (IOException e) {
                /* should not be thrown */
            }
        }
    }

    return false;
}

They are checking the DatagramSocket as well to check if the port is avaliable in UDP and TCP.

Hope this helps.


For Java 7 you can use try-with-resource for more compact code:

private static boolean available(int port) {
    try (Socket ignored = new Socket("localhost", port)) {
        return false;
    } catch (IOException ignored) {
        return true;
    }
}

It appears that as of Java 7, David Santamaria's answer doesn't work reliably any more. It looks like you can still reliably use a Socket to test the connection, however.

private static boolean available(int port) {
    System.out.println("--------------Testing port " + port);
    Socket s = null;
    try {
        s = new Socket("localhost", port);

        // If the code makes it this far without an exception it means
        // something is using the port and has responded.
        System.out.println("--------------Port " + port + " is not available");
        return false;
    } catch (IOException e) {
        System.out.println("--------------Port " + port + " is available");
        return true;
    } finally {
        if( s != null){
            try {
                s.close();
            } catch (IOException e) {
                throw new RuntimeException("You should handle this error." , e);
            }
        }
    }
}

If you're not too concerned with performance, you could always try listening on a port using the ServerSocket class. If it throws an exception odds are it's being used.

public static boolean isAvailable(int portNr) {
  boolean portFree;
  try (var ignored = new ServerSocket(portNr)) {
      portFree = true;
  } catch (IOException e) {
      portFree = false;
  }
  return portFree;
}

EDIT: If all you're trying to do is select a free port then new ServerSocket(0) will find one for you.


The following solution is inspired by the SocketUtils implementation of Spring-core (Apache license).

Compared to other solutions using Socket(...) it is pretty fast (testing 1000 TCP ports in less than a second).

Of course it can only detect services that open a port on all interfaces or that explicitly run on localhost.

public static boolean isTcpPortAvailable(int port) {
    try (ServerSocket serverSocket = new ServerSocket()) {
        // setReuseAddress(false) is required only on OSX, 
        // otherwise the code will not work correctly on that platform          
        serverSocket.setReuseAddress(false);
        serverSocket.bind(new InetSocketAddress(InetAddress.getByName("localhost"), port), 1);
        return true;
    } catch (Exception ex) {
        return false;
    }
}