when does java nio selector unblock on select() call
I am learning the NIO package. I refer the NioServer example from here. The selector thread in NioServer.java
blocks on
this.selector.select();
Iterator<SelectionKey> selectedKeys = this.selector.selectedKeys().iterator();
while (selectedKeys.hasNext()) {
SelectionKey key = selectedKeys.next();
selectedKeys.remove();
if (!key.isValid()) {
continue;
}
if (key.isAcceptable()) {
this.accept(key);
} else if (key.isReadable()) {
this.read(key);
} else if (key.isWritable()) {
this.write(key);
}
When a remote client connects, this.accept(key)
is called and in this method the interest
interestOps is changed to Read and awakes the selector.
is this what causes the selector to select this channel? So we signal in this way for the channel to be picked?
Now suppose in write to a socket channel selector is signalled by changing the interest that the channel is ready for write. But suppose in write did not开发者_StackOverflow社区 complete due to socket buffer full as shown in code, then we don't change the interest and keep it as is as write only. then when will the selector select this channel?
this.accept(key)
callsserverSocketChannel.accept()
which returns a new socket channel for communication with the client. It's this channel that is registered with the selector for "read" operations, i.e. the selector now has two registrations:- the original ServerSocketChannel, with OP_ACCEPT
- the SocketChannel for the new client, with OP_READ
If a write cannot complete due to the buffer filling up, the corresponding SocketChannel remains registered with OP_WRITE. Once the client reads some data off the other end, the channel will be selected again, allowing us to write the remaining data before flipping the interest set back to OP_READ.
OP_WRITE triggers when then there is room in the socket send buffer.
NB getting a zero length write() result is the only occasion for using OP_WRITE. Most of the time there is room, so OP_WRITE will keep triggering. You don't want this, so you normally don't have OP_WRITE registered for a channel: only when it has just returned zero from write; and you deregister it when that write eventually completes via being re-triggered after an OP_WRITE.
精彩评论