java nio 选择器何时在 select() 调用上解除阻塞
我正在学习 NIO 包。我参考了此处中的 NioServer 示例。 NioServer.java
中的选择器线程阻塞
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);
}
当远程客户端连接时,调用 this.accept(key)
并且在此方法中感兴趣 interestOps 更改为 Read 并唤醒选择器。 这是导致选择器选择该通道的原因吗?那么我们以这种方式发出信号来选择频道?
现在假设在写入套接字通道选择器时通过更改 感兴趣的是通道已准备好写入。 但是,假设由于套接字缓冲区已满,写入未完成(如代码所示),那么我们不会更改兴趣并将其保持为仅写入状态。 那么选择器什么时候会选择这个通道呢?
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 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
this.accept(key)
调用serverSocketChannel.accept()
,它返回一个新套接字通道用于与客户端通信。 这个通道向选择器注册以进行“读取”操作,即选择器现在有两个注册:如果由于缓冲区已满而无法完成写入,则相应的 SocketChannel 仍保持注册到 OP_WRITE。一旦客户端从另一端读取了一些数据,通道将被再次选择,允许我们在将兴趣集翻转回 OP_READ 之前写入剩余的数据。
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: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 就会触发。
注意,获得零长度 write() 结果是使用 OP_WRITE 的唯一场合。大多数时候还有空间,所以OP_WRITE会不断触发。您不希望这样,因此通常不会为通道注册 OP_WRITE:仅当它刚刚从写入返回零时;当写入最终完成时,您可以通过在 OP_WRITE 后重新触发来取消注册它。
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.