Tuesday, September 18, 2007

Windows Vista, Sockets, Java NIO, and TIME_WAIT

Blogging on behalf of Shrideep Pallickara:

When you are working with NIO sockets on Microsoft Vista you may run into a
problem where you will sometimes be able to connect to a specific host/port
combination, and sometimes the following error related to a bind exception
would be thrown:
java.net.SocketException: Invalid argument: sun.nio.ch.Net.setIntOption
...


The reason this happens is that when a connection is closed it goes into a
TIME_WAIT state. This can be checked with a tool such as netstat. Sometimes,
it can take up to a couple of minutes to get out of this state. When you try
to establish connections to the same host/port combination at a later time
you may not be able to establish this connection, because the previous
connection is still in a timeout state.

To get around this problem you need to configure your socket so that it can
reuse addresses. With this fix you can bind a socket to the specified
Address even if there is a connection in the timeout state that utilizes the
socket's address or port.

Please note that on the client side you will need to configure the setup
BEFORE you bind the socket. The code below shows how you do this for NIO.
You will need to wrap this code-fragment in the appropriate try-catch block.


SocketChannel sc = SocketChannel.open();
sc.socket().setReuseAddress(true);
sc.socket().setKeepAlive(true);
sc.configureBlocking(false);

InetSocketAddress ia = new InetSocketAddress(_hostName, _portNum);
sc.connect(ia);

You will also need to do a similar configuration on the Server side of the
socket as well.

1 comment:

Jef said...

Hello, your article is correct, but many points are missing. To avoid having a TIMEWAIT, we can flag the socket SO_REUSE, but this is not advised to do so (you could explain the dangers), otherwise it would be the defaut behaviour of a socket. In general, when I have a socket connection problem, I launch netstat and if it is only a TIMEWAIT problem, I wait untill it disappears. It is always less than 2 minutes. SO_REUSE is more usefull on the server side of a socket. On the client side, the port number should be dynamic, but if it is mandatory to have it static, you can reserve two port numbers and bind to the second one when the first one is in TIMEWAIT.