221

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?

Roman
  • 124,451
  • 167
  • 349
  • 456

19 Answers19

314

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");
}
Graham Edgecombe
  • 3,733
  • 1
  • 19
  • 12
  • 3
    When using new ServerSocket(0), care should be taken to close it! Based on http://javasourcecode.org/html/open-source/eclipse/eclipse-3.5.2/org/eclipse/jdt/launching/SocketUtil.java.html, slightly adapted in my https://gist.github.com/3429822 – vorburger Aug 22 '12 at 22:09
  • 12
    @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.) – Graham Edgecombe Sep 04 '12 at 12:49
  • 8
    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. – vorburger Sep 14 '12 at 11:44
  • 4
    @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. – Joker_vD Jun 25 '14 at 08:11
  • 2
    @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 Mar 22 '17 at 09:45
  • 1
    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. – khm Feb 22 '18 at 19:51
  • 1
    @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 Nov 20 '19 at 09:12
  • 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. – Graeme Moss Jun 17 '20 at 10:29
61

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

Maurice Perry
  • 32,610
  • 9
  • 70
  • 97
  • 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. – Roman Apr 20 '10 at 13:25
  • 1
    @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. – FrustratedWithFormsDesigner Apr 20 '10 at 13:30
45

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.

Andrei Savu
  • 8,525
  • 7
  • 46
  • 53
  • 1
    This might not work if you don't set `SO_REUSEADDR`. And there's a race condition, but it's hard to fix that. – David Ehrmann Jun 29 '15 at 04:40
  • 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. – user207421 Mar 22 '17 at 09:46
  • 7
    @EJP Sometimes third party code accepts a port but not the socket itself. – Captain Man May 23 '18 at 16:44
  • @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 Nov 20 '19 at 09:14
  • @user207421 You can't change third party code to accept a `ServerSocket` instead of an `int` for the port though. – Captain Man Nov 20 '19 at 15:49
37

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.

Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
Andy Johnson
  • 7,938
  • 4
  • 33
  • 50
  • 14
    +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(https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml)]" page, based on [RFC 6335 - Section 6](https://tools.ietf.org/html/rfc6335#section-6) (i.e. "Solid" reference in this case! :) ). – OzgurH Aug 24 '17 at 09:30
28

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;
    }
}
Serhii Bohutskyi
  • 2,261
  • 2
  • 28
  • 28
  • was wondering how to check a port, then unbind from it. Thanks SergeyB! – Vlad Ilie Apr 05 '16 at 06:24
  • 9
    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. – Simon Kissane Dec 15 '16 at 05:33
  • 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 Nov 20 '19 at 09:11
24

If you use Spring you may try http://docs.spring.io/spring/docs/4.0.5.RELEASE/javadoc-api/org/springframework/util/SocketUtils.html#findAvailableTcpPort--

Michail Nikolaev
  • 3,733
  • 22
  • 18
  • 5
    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)`. – Alexey Berezkin Dec 26 '19 at 08:04
  • 3
    Unfortunately `SocketUtils` class is deprecated now and will be removed in Spring 6.0. – pTak Dec 08 '22 at 14:09
11

The Eclipse SDK contains a class SocketUtil, that does what you want. You may have a look into the git source code.

KevinL
  • 1,238
  • 11
  • 28
jopa
  • 1,109
  • 7
  • 6
8

See ServerSocket:

Creates a server socket, bound to the specified port. A port of 0 creates a socket on any free port.

fospathi
  • 537
  • 1
  • 6
  • 7
f1sh
  • 11,489
  • 3
  • 25
  • 51
8

This works for me on Java 6

    ServerSocket serverSocket = new ServerSocket(0);
    System.out.println("listening on port " + serverSocket.getLocalPort());
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
7

I have recently released a tiny library for doing just that with tests in mind. Maven dependency is:

<dependency>
    <groupId>me.alexpanov</groupId>
    <artifactId>free-port-finder</artifactId>
    <version>1.0</version>
</dependency>

Once installed, free port numbers can be obtained via:

int port = FreePortFinder.findFreeLocalPort();
Alex Panov
  • 758
  • 10
  • 11
5

If your server starts up, then that socket was not used.

EDIT

Something like:

ServerSocket s = null ;

try { 
    s = new ServerSocket( 0 ); 
} catch( IOException ioe ){
   for( int i = START; i < END ; i++ ) try {
        s = new ServerSocket( i );
    } catch( IOException ioe ){}
}
// At this point if s is null we are helpless
if( s == null ) {
    throw new IOException(
       Strings.format("Unable to open server in port range(%d-%d)",START,END));
}
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • 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. – jonescb Apr 20 '10 at 13:22
  • 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 Apr 20 '10 at 13:22
  • 2
    @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. – OscarRyz Apr 20 '10 at 16:27
  • This code keeps opening and leaking `ServerSockets` forever and only retains the *last* one that succeeded. It needs a `break` statement. – user207421 Nov 20 '19 at 09:16
4

If you want to create your own server using a ServerSocket, you can just have it pick a free port for you:

  ServerSocket serverSocket = new ServerSocket(0);
  int port = serverSocket.getLocalPort();

Other server implementations typically have similar support. Jetty for example picks a free port unless you explicitly set it:

  Server server = new Server();
  ServerConnector connector = new ServerConnector(server);
  // don't call: connector.setPort(port);
  server.addConnector(connector);
  server.start();
  int port = connector.getLocalPort();
oberlies
  • 11,503
  • 4
  • 63
  • 110
3

It may not help you much, but on my (Ubuntu) machine I have a file /etc/services in which at least the ports used/reserved by some of the apps are given. These are the standard ports for those apps.

No guarantees that these are running, just the default ports these apps use (so you should not use them if possible).

There are slightly more than 500 ports defined, about half UDP and half TCP.

The files are made using information by IANA, see IANA Assigned port numbers.

extraneon
  • 23,575
  • 2
  • 47
  • 51
3

If you are using Spring, the answer provided by Michail Nikolaev is the simplest and cleanest one, and IMO should be upvoted. Just for convenience purposes, I'll add an inline example using the Springframwework SocketUtils.findAvailableTcpPort() method:

int randomAvailablePort = SocketUtils.findAvailableTcpPort();

It's as easy as that, just one line :). Of course, the Utils class offer many other interesting methods, I suggest having a look at the docs.

Gerardo Roza
  • 2,746
  • 2
  • 24
  • 33
2

If you are using the Spring Framework, the most straightforward way to do this is:

private Integer laancNotifyPort = SocketUtils.findAvailableTcpPort();

You can also set an acceptable range, and it will search in this range:

private Integer laancNotifyPort = SocketUtils.findAvailableTcpPort(9090, 10090);

This is a convenience method that abstracts away the complexity but internally is similar to a lot of the other answers on this thread.

anataliocs
  • 10,427
  • 6
  • 56
  • 72
1

Using 'ServerSocket' class we can identify whether given port is in use or free. ServerSocket provides a constructor that take an integer (which is port number) as argument and initialise server socket on the port. If ServerSocket throws any IO Exception, then we can assume this port is already in use.

Following snippet is used to get all available ports.

for (int port = 1; port < 65535; port++) {
         try {
                  ServerSocket socket = new ServerSocket(port);
                  socket.close();
                  availablePorts.add(port);
         } catch (IOException e) {

         }
}

Reference link.

Hari Krishna
  • 3,658
  • 1
  • 36
  • 57
1

There are a lot of answers here where ServerSocket is used. I checked Micronauts implementation and they instead try to connect a client socket to the port locally and if that fails they say the port is open. That to me has the advantage that they do not risk using the port within the test.

Their code looks like this:

    public static boolean isTcpPortAvailable(int currentPort) {
        try (Socket socket = new Socket()) {
            socket.connect(new InetSocketAddress(InetAddress.getLocalHost(), currentPort), 20);
            return false;
        } catch (Throwable e) {
            return true;
        }
    }

See here for reference: https://github.com/micronaut-projects/micronaut-core/blob/3.4.x/core/src/main/java/io/micronaut/core/io/socket/SocketUtils.java

Robert Sjödahl
  • 734
  • 5
  • 19
  • That's an interesting approach, although there is again the possibility of race condition. I may test to see which one works faster on my setup, so that it has lower probability of returning 'wrong result' due to race condition. – dragi Feb 24 '23 at 16:20
0

You can ask the ServerSocket to find a port for you then close it:

private int getFreePort() {
        var freePort = 0;
        try (ServerSocket s = new ServerSocket(0)) {
            freePort = s.getLocalPort();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return freePort;
    }
AHH
  • 981
  • 2
  • 10
  • 26
0

Many people mention the Spring framework utility, but if you are not using Spring, the logic of the utility is pretty simple and better than most of the answers because it gives a truly random result.

Here is the full source.

But here is the simplified source that you could just use in your own project without adding Spring as a dependency:

public static int findAvailableTcpPort() {
    int minPort = 1024;
    int maxPort = 65535;
    int portRange = maxPort - minPort;
    int maxAttempts = 1000;
    int candidatePort;
    int searchCounter = 0;
    Random random = new Random(System.nanoTime());
    do {
        if (searchCounter > maxAttempts) {
            throw new IllegalStateException(String.format(
                "Could not find an available TCP port in the range [%d, %d] after %d attempts",
                minPort, maxPort, maxAttempts));
        }
        candidatePort = minPort + random.nextInt(portRange + 1);
        searchCounter++;
    } while (!isPortAvailable(candidatePort));

    return candidatePort;
}

private static boolean isPortAvailable(int port) {
    try {
        ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(port, 1, InetAddress.getByName("localhost"));
        serverSocket.close();
        return true;
    } catch (Exception ex){
        return false;
    }
}
Jared Beach
  • 2,635
  • 34
  • 38