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.