是否可以在没有高CPU使用率的情况下将NIO保持在OP_WRITE模式

时间:2016-05-15 17:26:00

标签: java android tcp nio

我有一个Android应用程序充当服务器,并通过TCP以任意间隔(5-60秒内)从传感器提供一些数据。客户端应用程序偶尔会通过同一连接发送小块数据。必须毫不拖延地发送和接收数据。

所有示例和教程(如此http://adblogcat.com/asynchronous-java-nio-for-dummies/)都显示或多或少相同的情况 - 阅读完成后,切换到OP_WRITE。写入完成后切换到OP_READ,依此类推。 显然它对我的情况不起作用。我尝试过像这样启用读取和写入

serverChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);

但它会使选择器循环不断地加载CPU。

我确定这个问题不是很正确,所以即使有人给我完全不同但有工作的想法或指出我错了,我也会很高兴。 我没有发布代码,因为它几乎与上述教程相同。

1 个答案:

答案 0 :(得分:3)

您的问题以及您引用的样本均基于谬误。 没有这样的东西作为'模式'在NIO。你可以随时阅读和书写,但如果在错误的时间完成,他们都可以做任何事情。

  • OP_READ触发意味着读取将返回数据或流结束,即套接字接收缓冲区中有数据或FIN。这通常是错误的,除非对等方发送了一些数据或关闭了他的连接结束。
  • OP_WRITE触发意味着写入将传输一些数据,即套接字发送缓冲区中有空间。这通常是 true ,这反过来又是选择它通常会吸引CPU的原因。
  • 通常只应为OP_READ注册一个频道。
  • 当你有东西要写的时候,写下来。
  • 当且仅当 write()返回零时,注册OP_WRITE的通道,记住您正在编写的缓冲区,然后返回到选择循环。
  • 当OP_WRITE触发此通道时,重复写入,如果完成,取消注册 OP_WRITE的通道。

互联网上有很多垃圾,在NIO方面尤其如此。你引用的众多问题(在这种材料中一遍又一遍地看到):

  • select()不是异步的;
  • '其中只有一个可以同时发生' false ;
  • 您不需要Selector' s'许可'写;
  • 注册OP_WRITE,等待你有东西要写,并且不知道套接字发送缓冲区是满的只是一个精心设计和毫无意义的浪费时间;
  • 您无法将已注册OP_ACCEPT的频道更改为读/写;
  • 关闭频道会取消密钥;
  • 关闭通道或插座关闭两者;
  • finishConnect()可以返回false;
  • write()可以返回零,或者小于提供的数据量;
  • OP_CONNECT只能在isConnectionPending()为真时触发。