How to find an available port?
Asked Answered
S

19

225

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?

Season answered 20/4, 2010 at 13:16 Comment(1)
if the port is occupied by another software the code will throw an IOExceptionMalformation
E
319

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");
}
Excitability answered 20/4, 2010 at 13:24 Comment(8)
When using new ServerSocket(0), care should be taken to close it! Based on javasourcecode.org/html/open-source/eclipse/eclipse-3.5.2/org/…, slightly adapted in my gist.github.com/3429822Kenti
@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.)Excitability
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.Kenti
@Kenti 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.Accentual
@Kenti 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.Vulvitis
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.Prynne
@Prynne It doesn't. That's why the question doesn't make sense. This answer answers the question, but the whole situation is untenable.Vulvitis
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.Superman
C
61

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

Confer answered 20/4, 2010 at 13:21 Comment(2)
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.Season
@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.Papotto
B
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.

Blackman answered 30/10, 2014 at 3:40 Comment(5)
This might not work if you don't set SO_REUSEADDR. And there's a race condition, but it's hard to fix that.Indianapolis
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.Vulvitis
@EJP Sometimes third party code accepts a port but not the socket itself.Linus
@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.Vulvitis
@Vulvitis You can't change third party code to accept a ServerSocket instead of an int for the port though.Linus
C
38

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.

Cohette answered 20/4, 2010 at 13:21 Comment(1)
+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! :) ).Castra
A
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;
    }
}
Autoharp answered 15/3, 2016 at 12:29 Comment(3)
was wondering how to check a port, then unbind from it. Thanks SergeyB!Sake
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.Gunwale
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.Vulvitis
A
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--

Antrim answered 7/7, 2014 at 16:25 Comment(3)
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).Adder
Unfortunately SocketUtils class is deprecated now and will be removed in Spring 6.0.Glomerate
TestSocketUtils is still there in Spring 6, but that's in spring-test, obviously.Vassili
G
11

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

Goldshlag answered 20/4, 2010 at 13:28 Comment(1)
Looking at Eclipse's code, they do the same thing as Graham Edgecombe's answerOresund
C
8

See ServerSocket:

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

Carroll answered 20/4, 2010 at 13:25 Comment(0)
S
8

This works for me on Java 6

    ServerSocket serverSocket = new ServerSocket(0);
    System.out.println("listening on port " + serverSocket.getLocalPort());
Scrawly answered 21/5, 2010 at 20:52 Comment(0)
G
8

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();
Glycosuria answered 9/5, 2015 at 15:54 Comment(0)
U
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));
}
Unworldly answered 20/4, 2010 at 13:18 Comment(4)
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.Hausner
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.Season
@Season 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.Unworldly
This code keeps opening and leaking ServerSockets forever and only retains the last one that succeeded. It needs a break statement.Vulvitis
W
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();
Willable answered 30/4, 2013 at 15:53 Comment(0)
H
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.

Highgrade answered 20/4, 2010 at 13:39 Comment(1)
there is a similar (and more complete, IIRC) list that comes as part of nmap. +1Quadrinomial
D
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.

Draw answered 16/11, 2018 at 11:8 Comment(1)
It is deprecated!!Supermarket
H
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.

Hinch answered 4/8, 2020 at 22:55 Comment(1)
SocketUtils has been marked deprecated for Spring Boot (Spring version?) 2.6.X...Interlink
S
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.

Solvent answered 3/4, 2020 at 6:2 Comment(0)
A
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

Agonic answered 6/5, 2022 at 6:39 Comment(1)
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.Empson
A
1

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;
    }
}
Aryl answered 3/8, 2023 at 13:30 Comment(0)
U
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;
    }
Unbonnet answered 3/5, 2022 at 12:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.