8

I want to find an open local port in some range.

How can I do that in the most efficient way, without connecting to the port.

KARASZI István
  • 30,900
  • 8
  • 101
  • 128
Erik Sapir
  • 23,209
  • 28
  • 81
  • 141

7 Answers7

6

If you want to find a local open port to bind a server to, then you can create a ServerSocket and if it does not throw an Exception, then it's open.

I did the following in one of my projects:

private int getAvailablePort() throws IOException {
    int port = 0;
    do {
        port = RANDOM.get().nextInt(20000) + 10000;
    } while (!isPortAvailable(port));

    return port;
}

private boolean isPortAvailable(final int port) throws IOException {
    ServerSocket ss = null;
    try {
        ss = new ServerSocket(port);
        ss.setReuseAddress(true);
        return true;
    } catch (final IOException e) {
    } finally {
        if (ss != null) {
            ss.close();
        }
    }

    return false;
}

RANDOM is a ThreadLocal here, but of course you can do an incrementing part there.

KARASZI István
  • 30,900
  • 8
  • 101
  • 128
3

There's a little problem you may face in a multitasking windows/unix environment: if some isPortAvailable(final int port) from any of the answers returns a true for you, that doesn't mean, that at the moment when you will actually bind it it still will be available. The better solution would be create a method

ServerSocket tryBind(int portRangeBegin, int portRangeEnd) throws UnableToBindException;

So that you will just launch it and receive open socket for you, on some available port in the given range.

Illarion Kovalchuk
  • 5,774
  • 8
  • 42
  • 54
1

If you mean port in a remote server, then you might need a library that support raw-socket to send a sync packet and wait for sync-ack packet, just like nmap does.

secmask
  • 7,649
  • 5
  • 35
  • 52
  • Local-port, you should parse output of `netstat` command, that's fast and no need a dependency. – secmask Aug 22 '11 at 08:02
0

One way to do is use some native network command and parse the output.

  1. You can try netstat command as its available on Windows and *nix platforms.
  2. Typical command would be netstat -n
  3. Its output is of following format. Netstat command output

  4. you need to parse the 'Foreign Address column for localhost or 127.0.0.1' and get a list of busy ports. Then see if they are in the range you specified.

Santosh
  • 17,667
  • 4
  • 54
  • 79
  • This won't work with IPv6 addresses, and what about the `0.0.0.0:*`, and you'll even have problems on those platforms where `netstat` is not available or works differently. – KARASZI István Aug 22 '11 at 08:18
  • You may be correct. Even though addressing scheme (128 bit compared to 32 bit) is different but the output format remains the same. For a java program the parsing is dealing with strings until you arrive a port number (after parsing ip:port). This should still work. – Santosh Aug 22 '11 at 08:30
  • Regarding other platforms, need to actually run those command see the output difference and change the program accordingly. @Erik can actually see the output of netstat command on the platform he is working for . – Santosh Aug 22 '11 at 08:31
0

If this is not about port-sniffing, but about service discovery, consider using a rendez-vous server (like an RMI server) or using the UDP protocol. Back in the day we used JXTA for this, but I hope there is a better alternative for this now.

Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60
0

Essentially the same idea as Karaszi, but instead of constructing that many sockets, use the InetSocketAddress and try to bind a ServerSocket to every address in range, until you hit an open one.

If you don't want to bind to that port (although if you don't, the socket may as well be bound the next moment after you check), use a plain Socket Object and try to connect to the ports - if it works, the port is taken, if it doesn't (and you don't have a firewall forbiding the connection), then it's most likely free.

0

Just pass zero as the port number to new ServerSocket(), then it will find one for you. But you can forget about the range, it will choose from the system-defined range.

user207421
  • 305,947
  • 44
  • 307
  • 483