How to find an available port?

206,568

Solution 1

If you don't mind the port used, specify a port of 0 to the ServerSocket constructor and it will listen on any free port.

ServerSocket s = new ServerSocket(0);
System.out.println("listening on port: " + s.getLocalPort());

If you want to use a specific set of ports, then the easiest way is probably to iterate through them until one works. Something like this:

public ServerSocket create(int[] ports) throws IOException {
    for (int port : ports) {
        try {
            return new ServerSocket(port);
        } catch (IOException ex) {
            continue; // try next port
        }
    }

    // if the program gets here, no port in the range was found
    throw new IOException("no free port found");
}

Could be used like so:

try {
    ServerSocket s = create(new int[] { 3843, 4584, 4843 });
    System.out.println("listening on port: " + s.getLocalPort());
} catch (IOException ex) {
    System.err.println("no available ports");
}

Solution 2

If you pass 0 as the port number to the constructor of ServerSocket, It will allocate a port for you.

Solution 3

Starting from Java 1.7 you can use try-with-resources like this:

  private Integer findRandomOpenPortOnAllLocalInterfaces() throws IOException {
    try (
        ServerSocket socket = new ServerSocket(0);
    ) {
      return socket.getLocalPort();

    }
  }

If you need to find an open port on a specific interface check ServerSocket documentation for alternative constructors.

Warning: Any code using the port number returned by this method is subject to a race condition - a different process / thread may bind to the same port immediately after we close the ServerSocket instance.

Solution 4

According to Wikipedia, you should use ports 49152 to 65535 if you don't need a 'well known' port.

AFAIK the only way to determine wheter a port is in use is to try to open it.

Solution 5

If you need in range use:

public int nextFreePort(int from, int to) {
    int port = randPort(from, to);
    while (true) {
        if (isLocalPortFree(port)) {
            return port;
        } else {
            port = ThreadLocalRandom.current().nextInt(from, to);
        }
    }
}

private boolean isLocalPortFree(int port) {
    try {
        new ServerSocket(port).close();
        return true;
    } catch (IOException e) {
        return false;
    }
}
Share:
206,568

Related videos on Youtube

Roman
Author by

Roman

Updated on May 06, 2022

Comments

  • Roman
    Roman almost 2 years

    I want to start a server which listen to a port. I can specify port explicitly and it works. But I would like to find a port in an automatic way. In this respect I have two questions.

    1. In which range of port numbers should I search for? (I used ports 12345, 12346, and 12347 and it was fine).

    2. How can I find out if a given port is not occupied by another software?

    • Cezar Terzian
      Cezar Terzian almost 4 years
      if the port is occupied by another software the code will throw an IOException
  • jonescb
    jonescb about 14 years
    Don't know who voted you down, but I voted you back up. You could set up a recursive function to tries to setup the ServerSocket, and if you get an IOException (or whatever it is), you try again until it successfully gets a port.
  • Roman
    Roman about 14 years
    I thinks it's better to check if a port is available and then try to start listening to this port. It's does not seem to be elegant to start something and then find out that there are some problem and then try to solve these problems.
  • Roman
    Roman about 14 years
    Yes, I think it's the most elegant solution but because of some reasons it does not work in my case. But I still need to find out what exactly is wrong.
  • FrustratedWithFormsDesigner
    FrustratedWithFormsDesigner about 14 years
    @Roman: Why doesn't it work? Update your question to include this (or people will keep suggesting it) and explain why this solution fails for you.
  • rmeador
    rmeador about 14 years
    there is a similar (and more complete, IIRC) list that comes as part of nmap. +1
  • OscarRyz
    OscarRyz about 14 years
    @Roman well, yes, that would be better, except for the fact there is no a method to know if a port is available. If new ServerSocket(0) is not working for your the alternative is this. I think there are 85% of possibilities you end up using my suggestion.
  • vorburger
    vorburger over 11 years
    When using new ServerSocket(0), care should be taken to close it! Based on javasourcecode.org/html/open-source/eclipse/eclipse-3.5.2/or‌​g/…, slightly adapted in my gist.github.com/3429822
  • Graham Edgecombe
    Graham Edgecombe over 11 years
    @vorburger, doing it in that manner is prone to race conditions. It's nicer to just listen on the server socket immediately, rather than open it to find a free port, close it again, and then open one again on the free port (by which time there is a small chance something else is now listening on that port.)
  • vorburger
    vorburger over 11 years
    agreed, but it depends on the exact use case: In my case I needed to find a free port number to hand it into some API (say an embedded Jetty starter, for tests) - the respective API wants a socket number - not an already opened server socket. So it depends.
  • Joker_vD
    Joker_vD almost 10 years
    @vorburger Reasonable APIs will accept zero as a valid port number to listen on, and then will tell you the actual port being listened on. Hovewer, there are not many reasonable APIs: many programs specifically test for 0 port being passed and refuse it (ssh -D 127.0.0.0:0 ...? Nope!), which is really frustrating. We had to patch quite a number of libraries/programs to make them of use to us.
  • KevinL
    KevinL about 9 years
    Looking at Eclipse's code, they do the same thing as Graham Edgecombe's answer
  • David Ehrmann
    David Ehrmann almost 9 years
    This might not work if you don't set SO_REUSEADDR. And there's a race condition, but it's hard to fix that.
  • Vlad Ilie
    Vlad Ilie about 8 years
    was wondering how to check a port, then unbind from it. Thanks SergeyB!
  • Simon Kissane
    Simon Kissane over 7 years
    If every port in the range [from,to) is in use, this code will loop infinitely (or at least until one of those ports becomes free). If you do a sequential scan rather than picking ports in the range at random, you can avoid this possibility (just throw an exception when you get to the end of the range without finding a free port). If you really need to pick ports at random, then you need a set to keep track of the ports you've tried so far, and then raise an error when the size of that set equals to - from.
  • user207421
    user207421 about 7 years
    @vorburger When using any port, care should be taken to close it. new ServerSocket(0) is not different in this respect. There is nothing whatsoever in your first link about this. Your second link merely exhibits poor practice. Once you've constructed the ServerSocket you should use it, not close it and try to reuse the same port number. All that is a complete waste of time, as well as being vulnerable to timing-window problems.
  • user207421
    user207421 about 7 years
    This might not work if you subsequently try to open another ServerSocket with the same port number, as it might have been taken in the meanwhile. Why you wouldn't just return the actual ServerSocket instead of closing it remains a mystery.
  • OzgurH
    OzgurH over 6 years
    +1. Since Wikipedia is not always the source of absolute truth/facts, I thought it may be useful to note that, the reference for that Wikipedia page comes from "Internet Assigned Numbers Authority (IANA)"s "[Service Name and Transport Protocol Port Number Registry(iana.org/assignments/service-names-port-numbers/…" page, based on RFC 6335 - Section 6 (i.e. "Solid" reference in this case! :) ).
  • khm
    khm about 6 years
    If the server is listening on a random port like this, how does the client know which port to send to? I tried this, but realized that the Socket() constructor on the client side needs a specific port to send to.
  • Captain Man
    Captain Man almost 6 years
    @EJP Sometimes third party code accepts a port but not the socket itself.
  • ed22
    ed22 almost 6 years
    How do I find this port from client? ;)
  • user207421
    user207421 over 4 years
    Port 0 is considerably simpler and doesn't require creating two ServerSockets in the success case, and doesn't suffer from the timing-window problems of this code.
  • user207421
    user207421 over 4 years
    @khm It doesn't. That's why the question doesn't make sense. This answer answers the question, but the whole situation is untenable.
  • user207421
    user207421 over 4 years
    @CaptainMan Sure, but in those cases the port is surely assumed to be preallocated. A dynamically allocated port has to be supplied to clients by some other mechanism such as a naming service or a broadcast or mulitcast. The whole question here is malformed.
  • user207421
    user207421 over 4 years
    This code keeps opening and leaking ServerSockets forever and only retains the last one that succeeded. It needs a break statement.
  • Captain Man
    Captain Man over 4 years
    @user207421 You can't change third party code to accept a ServerSocket instead of an int for the port though.
  • Alexey Berezkin
    Alexey Berezkin over 4 years
    For those who is curious, under the hood SpringUtils.findAvailableTcpPort() is doing exactly the same recommended in other answers: pick a port then try new ServerSocket(port).
  • Graeme Moss
    Graeme Moss almost 4 years
    My use case is worse in that I know multiple JVMs will use the same code to find their own free port at the same time, and it seems there's some likelyhood in them picking the same port via port 0 (or I was very unlucky), increasing the chance of a race hazard during the time between closing the port and handing it to the API to be used. Maybe picking a random number like @Serhii Bohutskyi suggests is better for me.
  • khmarbaise
    khmarbaise about 2 years
    SocketUtils has been marked deprecated for Spring Boot (Spring version?) 2.6.X...
  • RamPrakash
    RamPrakash almost 2 years
    It is deprecated!!