Basically our app uses one thread to perform a select on multiple socket channels. When a socket is closed (either remotely or locally) the server app needs to unregister the client (so we need to detect closed channels). We've been using blocking IO previously (no dramas), but now we're dealing with many connections/clients we need to rework it as we're getting excessive amounts of threads. Anyway, that's just background.
Here's the problem we're getting, I have boiled it down to the following.
SocketChannel channel = SocketChannel.open();
channel.connect(socketAddress); // for the test this is localhost.
// this make sure socket is open, remote end just echos, waits 3 seconds and closes the socket.
channel.write(ByteBuffer.wrap("testLocalSocketClose\n".getBytes()));
channel.configureBlocking(false);
Selector selector = Selector.open();
LOG.fine("registering channel");
channel.register(selector, SelectionKey.OP_READ, channel);
LOG.fine("closing channel");
channel.close();
LOG.fine("waiting...");
int i = selector.select();
// this never happens (or it does very rarely)
LOG.fine("selector woke with " + i + " selected");
I would have expected the selector to return the selection key of the dead channel. Given that it doesn't and this scenario is possible (channel closing just after a read operation but before another select is called - in separate threads obviously). How can we reliably detect/be informed that the channel has been closed?
(I saw somewhere someone mention adding the OP_WRITE to the key, I have tried this as well and it makes no difference).
Many Thanks.
Bob.