143

How do I programmatically determine the availability of a port in a given machine using Java?

i.e given a port number, determine whether it is already being used or not?.

om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
user54075
  • 1,431
  • 2
  • 10
  • 3
  • 2
    While this question is about how to know if a given port is already in use, you may have landed here trying to find a way to obtain a free port number, which http://stackoverflow.com/questions/2675362/how-to-find-an-available-port (with link to my https://gist.github.com/3429822) covers better. – vorburger Aug 22 '12 at 22:12
  • For what purpose? If you just want to find a vacant socket to listen at, just specify zero. Any scanning technique is liable to timing-window problems: the port can be vacant when you scan and occupied when you go to claim in. – user207421 Feb 28 '16 at 19:38

10 Answers10

97

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.

starball
  • 20,030
  • 7
  • 43
  • 238
David Santamaria
  • 8,671
  • 7
  • 33
  • 43
  • 5
    A nice variant of this if you have MINA is AvailablePortFinder.getNextAvailable(1024) which gets you the next non-privileged port. – Alain O'Dea Jun 27 '11 at 18:24
  • 9
    This doesn't catch everything however. I've been bitten by a running nginx on TCP 8000 whilst the above routine reports 8000 as available. No idea why -- I suspect nginx does some sneaky stuff (this is on OS X). Workaround for me is to do the above and also to open a new Socket("localhost", port) then return false if we don't get an exception. Thoughts? – Partly Cloudy Jan 16 '12 at 22:59
  • I've had the same issue with OS X. – OmerGertel Feb 28 '12 at 19:59
  • 2
    Same issue on Windows trying to detect if papercut SMTP server is running. A solution where you open a connection to a port, rather than trying to bind to a it (as suggested by Partly Clodys comment and Ivan's answer) seems to work more reliable. – stian Dec 06 '12 at 12:46
  • 5
    Interesting. The call to setReuseAddress() is completely pointless after the socket is already bound, and it it also completely contrary to the purpose of the code. – user207421 Mar 30 '13 at 23:59
  • without setReuseAddress the port would not be free to use for some time after closing the socket. Actually its a system call that gets called after bounding a socket – madz Mar 14 '15 at 22:58
  • 1
    @pendrive Actually it is a system call that should be called *before* binding a socket. Calling it afterwards is a complete waste of time. – user207421 Dec 01 '15 at 08:40
  • 3
    THis code is subject to timing-window problems. If the objective is to create a `ServerSocket` listening to some port, that's what it should do, and return the `ServerSocket`. Creating it and then closing it and returning it provides zero guarantee that a subsequent `ServerSocket` can be created using that port. Ditto for `DatagramSocket`. – user207421 Dec 01 '15 at 08:41
48

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

private static boolean available(int port) throws IllegalStateException {
    try (Socket ignored = new Socket("localhost", port)) {
        return false;
    } catch (ConnectException e) {
        return true;
    } catch (IOException e) {
        throw new IllegalStateException("Error while trying to check open port", e);
    }
}
Noam Yizraeli
  • 4,446
  • 18
  • 35
eivindw
  • 1,939
  • 17
  • 13
  • 20
    This doesn't test whether at port is available. It tests whether it is in LISTEN state, whether the IP address is reachable, etc. – user207421 Jul 27 '15 at 22:55
  • 1
    Additionally this test is pretty slow (nearly a second per port). – JMax Feb 16 '18 at 14:23
  • shouldn't it return false when an IOException is caught? – Baroudi Safwen Aug 06 '19 at 09:49
  • @BaroudiSafwen It depends entirely on what the exception actually is. For `ConnectException: 'connection refused'`, yes it should return false. For timeouts, nothing it could return would be valid, as the actual answer isn't known. That's why this technique is useless for this purpose. – user207421 Nov 25 '19 at 11:12
  • @BaroudiSafwen if the port you passed is being used, it will *not* throw an exception, returning `false` from the body of the _try_ block. In contrast, if the port *is not* in use, it will throw an exception, in which case, you want the method to return `true`. However, as JMax commented, this test is slow. – hfontanez Mar 31 '22 at 15:57
42

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);
            }
        }
    }
}
Community
  • 1
  • 1
TwentyMiles
  • 4,063
  • 3
  • 30
  • 37
38

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.

Eliezer
  • 7,209
  • 12
  • 56
  • 103
Spencer Ruport
  • 34,865
  • 12
  • 85
  • 147
  • Use finally for cleanup (try { ... } catch { ... } finally { if (socket != null) socket.close(); } – Hosam Aly Jan 12 '09 at 07:51
  • You can also set "portTaken = (socket == null);" at the end instead of doing it in the catch. – Hosam Aly Jan 12 '09 at 07:52
  • This attempts to bind to the socket on all (0.0.0.0) interfaces. You can use explicit addresses to check specific ports on specific addresses. see http://java.sun.com/j2se/1.4.2/docs/api/java/net/ServerSocket.html#ServerSocket(int,%20int,%20java.net.InetAddress) – cletus Jan 12 '09 at 08:32
  • 1
    I didn't feel that fell within the intended scope of the author's question. – Spencer Ruport Jan 12 '09 at 08:35
  • A minor mistake that an initialization should be: ServerSocket serverSocket = null; – royalghost Apr 16 '09 at 22:04
  • 1
    Is there a way to do it without try/catch? I wouldn't mind using *any* available port for my purposes, but iterating over port numbers and try/catch-ing over each one until I find a free one is a little wasteful. Isn't there a 'native boolean available(int)' method somewhere, which just checks? – Oren Shalev May 21 '09 at 12:41
  • 30
    new SeverSocket(0) will automatically select a free port . – Spencer Ruport May 21 '09 at 16:32
  • I have the same requirement as Oz. However, ServerSocket(0) sounds like a good second-best, so I've upvoted both these comments. I think ServerSocket(0) is worth putting as a separate full answer in fact. – Hugh Perkins Apr 09 '11 at 01:16
  • @HughPerkins It is a much better *first*-best. – user207421 Nov 25 '19 at 11:16
  • @Hosam Aly: Socket implements the Closable interface. The try-catch-finally (with ressource) will call the socket.close() for you. – primehunter Apr 28 '22 at 13:40
  • @primehunter: that wasn't an option in 2009 :) – Hosam Aly Apr 30 '22 at 07:23
15

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 macOS, 
        // 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;
    }
}       
JMax
  • 1,134
  • 1
  • 11
  • 20
5

A cleanup of the answer pointed out by David Santamaria:

/**
 * Check to see if a port is available.
 *
 * @param port
 *            the port to check for availability.
 */
public static boolean isPortAvailable(int port) {
    try (var ss = new ServerSocket(port); var ds = new DatagramSocket(port)) {
        return true;
    } catch (IOException e) {
        return false;
    }
}

This is still subject to a race condition pointed out by user207421 in the comments to David Santamaria's answer (something could grab the port after this method closes the ServerSocket and DatagramSocket and returns).

Verhagen
  • 3,885
  • 26
  • 36
Luke Hutchison
  • 8,186
  • 2
  • 45
  • 40
4

The try/catch socket based solutions , might not yield accurate results (the socket address is "localhost" and in some cases the port could be "occupied" not by the loopback interface and at least on Windows I've seen this test fails i.e. the prot falsely declared as available).

There is a cool library named SIGAR , the following code can hook you up :

Sigar sigar = new Sigar();
int flags = NetFlags.CONN_TCP | NetFlags.CONN_SERVER | NetFlags.CONN_CLIENT;             NetConnection[] netConnectionList = sigar.getNetConnectionList(flags);
for (NetConnection netConnection : netConnectionList) {
   if ( netConnection.getLocalPort() == port )
        return false;
}
return true;
Avi Cherry
  • 3,996
  • 1
  • 26
  • 31
Shmil The Cat
  • 4,548
  • 2
  • 28
  • 37
  • I get: "no sigar-x86-winnt.dll in java.library.path" Unfortunately it requires download of some additional dll that is not really viable in enterprise environment (I have no control over CI system). So bad.... Thanks anyway. – uthomas Apr 18 '13 at 14:02
  • @uthomas I guess you still have control on your app deployment package, if this is the case you can always provide Sigar native runtime DLL/SOs near your JARs and set the JAVA lib path pragmatically (via simple hack you can influence it even after your app has launched by the JVM). – Shmil The Cat Apr 19 '13 at 10:04
1

In my case it helped to try and connect to the port - if service is already present, it would respond.

    try {
        log.debug("{}: Checking if port open by trying to connect as a client", portNumber);
        Socket sock = new Socket("localhost", portNumber);          
        sock.close();
        log.debug("{}: Someone responding on port - seems not open", portNumber);
        return false;
    } catch (Exception e) {         
        if (e.getMessage().contains("refused")) {
            return true;
    }
        log.error("Troubles checking if port is open", e);
        throw new RuntimeException(e);              
    }
Ivan
  • 3,781
  • 16
  • 20
0

In my case I had to use DatagramSocket class.

boolean isPortOccupied(int port) {
    DatagramSocket sock = null;
    try {
        sock = new DatagramSocket(port);
        sock.close();
        return false;
    } catch (BindException ignored) {
        return true;
    } catch (SocketException ex) {
        System.out.println(ex);
        return true;
    }
}

Don't forget to import first

import java.net.DatagramSocket;
import java.net.BindException;
import java.net.SocketException;
kmchmk
  • 592
  • 9
  • 16
-2

I have Tried something Like this and it worked really fine with me

            Socket Skt;
            String host = "localhost";
            int i = 8983; // port no.

                 try {
                    System.out.println("Looking for "+ i);
                    Skt = new Socket(host, i);
                    System.out.println("There is a Server on port "
                    + i + " of " + host);
                 }
                 catch (UnknownHostException e) {
                    System.out.println("Exception occured"+ e);

                 }
                 catch (IOException e) {
                     System.out.println("port is not used");

                 }
mayu jadhv
  • 29
  • 10