Finding two free tcp ports
I understand that the following code can (perhaps not very efficiently) find out a free TC开发者_StackOverflow中文版P 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?
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;
}
One way to get two different port numbers:
ServerSocket socket1 = new ServerSocket(0);
port1 = socket1.getLocalPort();
ServerSocket socket2 = new ServerSocket(0);
port2 = socket2.getLocalPort();
socket1.close();
socket2.close();
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.
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.
Here's a class that I have used to find multiple free ports. It provides the flexibility to allocate individual ports in the flow of some complex logic (i.e. when maybe the number of ports you'll need is not a simple number but depends on complex logic). It still guarantees that all the ports you ask for free and unique (as long as you are using the same instance of this class to obtain all the ports).
So the way to use this class would be to create an instance. Execute your code to do whatever it is you want to allocate ports for using that instance. Then, once you have bound all the ports you can dispose of this instance and use a new one next time.
public class PortFinder {
/**
* If you only need the one port you can use this. No need to instantiate the class
*/
public static int findFreePort() throws IOException {
ServerSocket socket = new ServerSocket(0);
try {
return socket.getLocalPort();
} finally {
try {
socket.close();
} catch (IOException e) {
}
}
}
private HashSet<Integer> used = new HashSet<Integer>();
/**
* Finds a port that is currently free and is guaranteed to be different from any of the
* port numbers previously returned by this PortFinder instance.
*/
public synchronized int findUniqueFreePort() throws IOException {
int port;
do {
port = findFreePort();
} while (used.contains(port));
used.add(port);
return port;
}
}
精彩评论