Java 选择器 OP_READ 如果数据已经可用则不会触发
Java Selector OP_READ not triggered if data is already available
我正在编写一个接受连接的 NIO 服务器
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
为了在接受连接和注册 OP_READ
之间创建竞争条件,让我们假设接受后,服务器等待 Thread.sleep(1000);
然后只注册读取
clientSocketChannel.register(selector, SelectionKey.OP_READ);
同时,由于延迟,一些客户端数据已经通过网络发送并且可用。
我遇到的是选择器不会触发 OP_READ
此现有数据,我必须手动强制读取。
OP_READ
然后为所有后续传入数据正确触发。
这是正常行为吗?尽管有一些数据准备好读取,但为什么它不触发?
Selector
(和 SelectableChannel
)的 javadoc 解释说 select()
调用 "have become selectable since the previous selection operation" 的频道,这对我来说意味着如果没有以前的 select离子操作它检查自注册以来的时间段,而不是之前。这意味着,是的,您看到的是预期的行为。
这也是合乎逻辑的 - 没有在 reads 中注册兴趣的频道没有理由跟踪传入数据,只有当你注册这样的兴趣时(即,在你注册 selector for OP_READ
),它开始监视传入数据。
底线是 - 您可能想要注册 select 或立即注册,而不是等待一秒钟再注册。
如果在收到 OP_ACCEPT 事件后你做了类似的事情:
SocketChannel client = serverSocket.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
你参加比赛的机会非常小,因为另一端必须:
- 找出接受的连接(涉及网络跃点),
- 向套接字写入一些数据,
- 数据必须通过网络,
以及您两次调用 accept() 和 register() 之间的所有操作,none 其中涉及通过网络传输数据。我非常怀疑在两者之间获取(完整的)数据是否现实(注意:它应该是一个完整的数据,否则其中一些会在注册后出现,因此会触发 select)。
我正在编写一个接受连接的 NIO 服务器
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
为了在接受连接和注册 OP_READ
之间创建竞争条件,让我们假设接受后,服务器等待 Thread.sleep(1000);
然后只注册读取
clientSocketChannel.register(selector, SelectionKey.OP_READ);
同时,由于延迟,一些客户端数据已经通过网络发送并且可用。
我遇到的是选择器不会触发 OP_READ
此现有数据,我必须手动强制读取。
OP_READ
然后为所有后续传入数据正确触发。
这是正常行为吗?尽管有一些数据准备好读取,但为什么它不触发?
Selector
(和 SelectableChannel
)的 javadoc 解释说 select()
调用 "have become selectable since the previous selection operation" 的频道,这对我来说意味着如果没有以前的 select离子操作它检查自注册以来的时间段,而不是之前。这意味着,是的,您看到的是预期的行为。
这也是合乎逻辑的 - 没有在 reads 中注册兴趣的频道没有理由跟踪传入数据,只有当你注册这样的兴趣时(即,在你注册 selector for OP_READ
),它开始监视传入数据。
底线是 - 您可能想要注册 select 或立即注册,而不是等待一秒钟再注册。
如果在收到 OP_ACCEPT 事件后你做了类似的事情:
SocketChannel client = serverSocket.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
你参加比赛的机会非常小,因为另一端必须:
- 找出接受的连接(涉及网络跃点),
- 向套接字写入一些数据,
- 数据必须通过网络,
以及您两次调用 accept() 和 register() 之间的所有操作,none 其中涉及通过网络传输数据。我非常怀疑在两者之间获取(完整的)数据是否现实(注意:它应该是一个完整的数据,否则其中一些会在注册后出现,因此会触发 select)。