开发者

How to find an available port?

开发者 https://www.devze.com 2022-12-27 07:03 出处:网络
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.

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?


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");
}


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


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.


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.


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;
    }
}


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--


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


This works for me on Java 6

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


See ServerSocket:

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


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();


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));
}


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();


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.


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.


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.


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.


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;
    }


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

0

精彩评论

暂无评论...
验证码 换一张
取 消