Java Mystery Of (Un)Closed Sockets
Windows has a limit on number of existing client network sockets. I recently ran into this when I started to close sockets which were previously left to be timed out. That was certainly a suprprise, because naturally one would thought that closed socket will be, well, closed much earlier than unclosed one.
I created a small test case:
public static void main(String[] args) throws Exception {
int i = 0;
while (true) {
Socket sock = openSocket();
OutputStream os = sock.getOutputStream();
os.write("GET / HTTP/1.1\n\n".getBytes());
InputStream is = sock.getInputStream();
while (is.read() != -1) {
// void
}
is.close();
os.close();
sock.close();
System.out.println("" + i++);
}
}
private static Socket openSocket() throws Exception {
InetAddress address = InetAddress.getByName("localhost");
Socket socket = new Socket(address, 80);
socket.setReuseAddress(true);
socket.setTcpNoDelay(true);
socket.setKeepAlive(true);
socket.setSoLinger(true, 0);
return socket;
}
The socket.setSoLinger(true, 0) should force the TCP connection
to be dropped immediately with connection reset when socket is closed.
I tried that (and modifications without setting of SO_LINGER(0) and without closing the streams and socket) on Windows XP Professional connecting to Apache 2.0.59 and got this (the numbers differ between executions, but there is a general trend visible in a number of successfully allocated sockets):
| closed with SO_LINGER(0) | closed normally | unclosed | |
|---|---|---|---|
| Java 5 | less | more | more |
| Java 6 | more | less | less |
Fortunately Java 6 behaves more logically. But, of course, anyone allocating that many sockets should be punished.
