socket.setReuseAddress(true); doesn't release the socket after
socket.close(). Why?
As I understand it, setReuseAddress() affects the behaviour of the socket as
the corresponding connection is set up (as it is bound()), not the behaviour of
the /next/ socket that attempts to bind to the same port. The problem is that
the Socket constructor that takes the name of a host opens the connection for
you, so the socket has already been bound() by the time that the constructor
returns (arguably this is bad design, although it is convenient), and so the
setReuseAddress() has no effect.
I believe (but see below) that the code to use for this kind of purpose should
be:
Socket socket = new Socket();
socket.setReuseAddress(true);
socket.connect(new InetSocketAddress(m_host, m_port));
However, either my understanding is wrong, or that code is incorrect, or
there's a bug somewhere in the Java implementation or the Windows (XP and 2K)
network stacks that I've tried it on. It seems that the bind() call (inside
Socket.connect()) still fails intermittently. For my purposes (which was just
a quick stress test of a custom server implementation), it was sufficient to
catch the error and ignore it. Running in a tight loop (at around 600
connection / second) that happened to about 5% of the connection attempts.
Which, I imagine is too low to be ascribed to genuine port exhaustion. More
importantly, it was low enough for me to ignore. My real code:
....loop...
Socket socket = new Socket();
socket.setReuseAddress(true);
socket.setTcpNoDelay(true);
try
{
socket.connect(new InetSocketAddress(m_host, m_port));
}
catch (BindException e)
{
bindErrors++;
continue;
}
....more code...
It would be nice to know what was really going wrong -- /especially/ if it's a
mistake on my part -- but at least I was able to run my tests...
-- chris