tags:

views:

63

answers:

4

I understand that the following code can (perhaps not very efficiently) find out a free TCP port in Java:

  public static int findFreePort() {
    int port;
    try {
      ServerSocket socket= new ServerSocket(0);
      port = socket.getLocalPort();
      socket.close(); 
    } catch (Exception e) { port = -1; }
    return port;    
  } 

(There are some related questions here in SO - for example).

What I don't understand is why (or whether) two succesive calls to this method are guaranteed to return two different ports. This is assumed, for example, here (search for the calls to findFreePort method).

Is this correct?

A: 

Source code for ServerSocket is here: http://kickjava.com/src/java/net/ServerSocket.java.htm

I'm not quite seeing how it determines if the port is free or not, but:

@param port the port number, or <code>0</code> to use any
free port.

So once the first port is allocated, even to your application, it is no longer free. So successive calls to ServerSocket will not reuse that port thus guaranteeing two different ports.

Freiheit
But `findFreePort` opens the socket and inmediately closes it, so in theory is again available.
leonbloy
In the code, the port is allocated, but the "close()" method disallocate this port. Then, it can be resused (by another ServerSocket, for example). So, I think another call to that method could give the same port number.
Benoit Courtine
A: 

In the Javadoc specification, I don't see any line saying that two succesive calls is guaranteed to return two different ports...

Since the ServerSocket is closed, a second call could give the same port. Statistically, it is unprobable but not impossible I think.

If you open your two ServerSocket, get the ports, and then, close your two ServerSocket, you are guarranted to get two different ports (since the first is not free when you create the second ServerSocket).

Example method to get n different free ports :

public int[] getFreePorts(int portNumber) throws IOException {
    int[] result = new int[portNumber];
    List<ServerSocket> servers = new ArrayList<ServerSocket>(portNumber);
    ServerSocket tempServer = null;

    for (int i=0; i<portNumber; i++) {
        try {
            tempServer = new ServerSocket(0);
            servers.add(tempServer);
            result[i] = tempServer.getLocalPort();
        } finally {
            for (ServerSocket server : servers) {
                try {
                    server.close();
                } catch (IOException e) {
                    // Continue closing servers.
                }
            }
        }
    }
    return result;
}
Benoit Courtine
Yes, I had just coded almost exactly the same method :-)
leonbloy
It should be noted that even this solution (and Noel M's) is not 100% foolproof, there is a potential race condition. After this method call, the caller will eventually try to use those available ports. But it could happen that in the meantime some other process has opened it.
leonbloy
+1  A: 

One way to get two different port numbers:

  ServerSocket socket1= new ServerSocket(0);
  port1 = socket.getLocalPort();
  ServerSocket socket2= new ServerSocket(0);
  port2 = socket.getLocalPort();

  socket1.close();
  socket2.close(); 
Noel M
A: 

It's as efficient as the operating system can make it. However closing the ServerSocket immediately afterwards is pointless, as that port is no longer reserved and can be allocated to something else. The only purpose of this exercise is to create a ServerSocket, so just create it.

EJP