We were curious as to what the handoff is between an application that opens a network socket, and how the Linux OS handles it.
Let’s assume we do what is below:
import java.net.*;
public class checkSocket {
public static void main(String args[]) throws Exception {
Socket s = new Socket();
s.connect(new InetSocketAddress(InetAddress.getByName("cmhldecomecm01"),10180));
System.out.println("created socket on port " + s.getLocalPort());
s.close();
System.out.println("closed socket, giving time to reuse port (hopefully)");
Thread.sleep(15000);
s = new Socket();
s.connect(new InetSocketAddress(InetAddress.getByName("cmhldecomecm01"),10180));
System.out.println("created socket on port " + s.getLocalPort());
s.close();
System.out.println("closed socket");
}
}
As you can see below, we open a second socket. Our keepalive time of 75 ensures whatever ports have been opened will remain open throughout the test.
-bash-4.1$ java checkSocket created socket on port 53572 closed socket, giving time to reuse port (hopefully) created socket on port 53573 closed socket -bash-4.1$ netstat -anp | grep 10180 tcp 0 0 ::ffff:172.28.37.26:53572 ::ffff:172.28.37.75:10180 TIME_WAIT - tcp 0 0 ::ffff:172.28.37.26:53573 ::ffff:172.28.37.75:10180 TIME_WAIT - -bash-4.1$
Notice that we end up creating two sockets, even when the first one has been closed by the application, but is open by the OS. Why doesn’t it reuse these sockets?
When we reconfigure the software to bind locally to a specific port, we see it can be reused.
import java.net.*;
public class checkSocket {
public static void main(String args[]) throws Exception {
Socket s = new Socket();
s.setReuseAddress(true);
s.connect(new InetSocketAddress(InetAddress.getByName("cmhldecomecm01"),10180));
System.out.println("created socket on port " + s.getLocalPort());
int p = s.getLocalPort();
s.close();
System.out.println("closed socket, giving time to reuse port (hopefully)");
Thread.sleep(15000);
s = new Socket();
s.setReuseAddress(true);
s.bind(new InetSocketAddress(InetAddress.getByName("cmhldecomatl01"),p));
s.connect(new InetSocketAddress(InetAddress.getByName("cmhldecomecm01"),10180));
System.out.println("created socket on port " + s.getLocalPort());
s.close();
System.out.println("closed socket");
}
}
…with the results below…
-bash-4.1$ java checkSocket created socket on port 53647 closed socket, giving time to reuse port (hopefully) created socket on port 53647 closed socket -bash-4.1$ netstat -anp | grep 10180 tcp 0 0 ::ffff:172.28.37.26:53647 ::ffff:172.28.37.75:10180 TIME_WAIT - -bash-4.1$
Any major java HTTP application server handles ports in the latter manner, to ensure resources are used efficiently.