I'm trying to write a socket server in java using the java nio classes. Only using non-blocking io, not async io.
I've got a single thread which calls the selector's select() method. Initially the only channel in the select list is a ServerSocketChannel. Each time select() returns I enumerate the selectedKeys() list and delegate the io to a separate io thread. Before I send the information to the io thread I first attempt to turn off the interest on the channel by setting the interestOps to zero. I do this so that the select() isn't firing anymore on that channel since it should continue to fire until the io has been performed. By the way, you can't accomplish this via the SelectionKey's cancel() method as that puts the channel on the cancelled list and it can't be added back to the selection list. cancel() is only for removing the channel from the list when you're done with it. I don't use cancel() at all since closing the socket() will automatically call cancel().
When the io thread finishes the io it communicates back to the select thread asking it to either close the socket or reset the interestOps to what they should be.
While this seems to be somewhat working, I've noticed that select() seems to continually return socket channels even when there are no bytes to read. By the way, the server is only reading from the socket and only sets the interest to OP_READ (or zero when I want to turn off the channel). To test a specific scenario I wrote a client which opens a socket, writes 1k bytes to it, sleeps 10 seconds, and then writes another 1k bytes to it then closes the socket. During this sleep time the select() call returns continuously and when I read the socket there are zero bytes returned. Obviously I don't want the select() loop firing continuously when there is no work to do as I would be pegging a CPU. I've set the channel up for non-blocking io. I should also mention that, similar to one of the threads I reference below, this behavior doesn't happen until the client opens the socket and starts sending data. In this case I still have the server socket channel I'm listening on for OP_ACCEPT and the select() call is not constantly firing for that.
Here are two similar, but different, threads:
Infinite loop with Selector even there's no connection from client
Some of the comments in those two threads talk about handling the EOF, -1 on read(), case. This is not the issue I'm having so please don't mark this as a duplicate of those.
Also, in one of those threads it sounded like someone suggested that since the socket channel is in non-blocking mode the select() will fire continuously regardless of whether there is, in my case data to read. This sounds very odd. I would find it hard to believe this is the way it's supposed to be working. I believe when I indicate I have an interest in read on a channel, select() should only return that channel in the selected list if there is data to read.
Thanks, Nick