【问题标题】:Is it possible to keep NIO in OP_WRITE mode without high CPU usage是否可以在没有高 CPU 使用率的情况下将 NIO 保持在 OP_WRITE 模式
【发布时间】:2016-09-11 12:07:20
【问题描述】:

我有一个 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 的负载。

我确定这个问题并不真正正确,所以即使有人给我完全不同但可行的想法或我错的地方,我也会很高兴。 我没有发布代码,因为它与前面提到的教程几乎相同。

【问题讨论】:

    标签: java android tcp nio


    【解决方案1】:

    您的问题和您引用的示例是基于一个谬误。在 NIO 中没有“模式”之类的东西。你可以随时阅读和写作,但如果在错误的时间完成,它们都将无能为力。

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

    互联网上有很多垃圾,在涉及 NIO 时尤其如此。在您引用的众多问题中(在此类材料中一遍又一遍地看到):

    • select() 不是异步的;
    • '一次只能发生其中一个'是false
    • 你不需要Selector的“权限”来写;
    • 注册 OP_WRITE 并在您有内容要写入但还不知道套接字发送缓冲区已满时等待它触发只是一种精心设计且毫无意义的浪费时间;
    • 您不能将已注册 OP_ACCEPT 的通道更改为读/写;
    • 关闭频道会取消密钥;
    • 关闭通道或套接字同时关闭;
    • finishConnect() 可以返回false;
    • write() 可以返回零或小于提供的数据量;
    • OP_CONNECT 只能在 isConnectionPending() 为真时触发。

    【讨论】:

      猜你喜欢
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      • 2014-06-16
      • 2020-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多