Does java reuse closed sockets when the host still has one open?

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.