NIO选择器在没有数据的情况下保持触发读取

时间:2017-03-22 08:12:55

标签: java nio

我有一个自定义NIO服务器,但我看到一个我无法重现或解释的行为:选择器使用isReadable() == true保持触发某个选择键但是当我从频道读取时,没有数据

我有:

  • 三重检查在所有情况下都遵守EOS
  • 构建自定义客户端,尝试各种无效数据的时髦组合来触发错误但不能自己触发
  • 浏览了apache mina代码,看看它们与我的服务器相比是否有什么特别之处
  • 尝试了不同版本的JDK(8_111和8_121)
  • triple检查选择键是否从包含iterator.next()之后的所有内容的finally块中的所选键集的迭代器中删除,因此它不应该是ghost键

一切都变空了,我在客户端尝试的每一个奇怪的事情都由服务器正确处理,但是大约每四个小时(你几乎可以设置一个时钟),来自俄罗斯的IP连接到服务器并触发这个错误。

此时选择器进入过驱动状态,不断触发通道和附加到它的读取过程,从而保持报告0字节的传入。

所以有两个问题:

  • 除了实际数据和EOS之外,还有什么可以触发选择器上的读取操作?
  • 如果我找不到实际的问题,可以直接检查x后续读取触发器数量,但没有数据,并得出结论我应该关闭套接字吗?有读取超时到位但由于错误的CPU密集性,它们太长了以至于我不舒服

更新

  • 服务器套接字通道不是触发读取而是一个接受的客户端通道,因此它不能(不应该?)成为传入连接
  • 默认情况下仅注册OP_READ,如果内部缓冲区仍包含数据但在数据发送后未注册,则偶尔注册OP_WRITE
  • 提到的读取超时是自定义超时,解析器将跟踪消息的第一个数据何时进入,如果完成时间太长,则会触发读取超时

如果我知道问题出在哪里,我可以提供该部分的一些代码,但整个服务器太大而无法粘贴在这里。

更新2

在我添加的调试内容中,我打印出以下状态:

selectionKey.isReadable() + "/" + selectionKey.isValid() + "/" + selectionKey.channel().isOpen()

所有三个布尔都是真的。

1 个答案:

答案 0 :(得分:1)

没有一些代码就无法正确回答这个问题,但是:

  

除了实际数据和EOS之外,还有什么可以触发选择器上的读操作?

如果是ServerSocketChannel,则为传入连接。

  

如果我找不到实际的问题,可以直接检查x数量的后续读取触发器,但没有数据,并得出结论我应该关闭套接字吗?

没有。在代码中找到错误。

  

有读取超时

非阻塞套接字上无法读取超时,并且当您使用Selector时,必须使用非阻塞套接字。

  

但是由于bug的CPU密集性,它们太长了以至于我不舒服

我不知道这意味着什么。