【问题标题】:Java NIO packet stickingJava NIO 数据包粘连
【发布时间】:2015-07-13 04:55:07
【问题描述】:

我有一个带有 NIO 实现的服务器,带有选择器。 实现相当简单:

            selector.select();
            Set<SelectionKey> keys = selector.selectedKeys();
            for (SelectionKey key : keys) {
                if (! key.isValid()) {
                    continue;
                }
                UserConnection connection = users.get(key);
                if (key.isReadable()) {
                    processReadableKey(key, connection);
                } else if (key.isWritable()) {
                    processWritableKey(key, connection);
                }

问题是,当两个数据包(消息)几乎立即一个接一个地到达时,选择器会做出反应并处理第一个,但随后它不会做出反应并将相应的键标记为“可读”以处理第二个。 当下一条消息到达时,选择器处理它,然后处理那个“丢失”的数据包。 我不知道,如何解决它。我尝试减少通道缓冲区,并尝试通过selector.wakeup() 唤醒选择器,但这没有帮助,因为问题与在处理这对夫妇的第一条消息后立即将密钥识别为“可读”有关。 有什么想法吗?

【问题讨论】:

  • nio 代码很难完全正确。这是一个非常棘手的 api。除非你需要为课程做这件事,否则我会使用像 netty 这样的框架,它隐藏了这种复杂性。
  • 选择器不会错过事件。你确定真的有两个包到了吗?

标签: java selector nio readable


【解决方案1】:

听起来您需要在使用它们之前从选定的键集中删除选择键。如果您不这样做,当您调用selectedKeys() 时,返回的集合仍将包含旧的、已使用的键。

类似的东西:

 Iterator iter = selector.selectedKeys().iterator();  
 while (iter.hasNext()) {  
     SelectionKey key = (SelectionKey) iter.next();  
     iter.remove();  // remove here 
     process(key);  
 }

【讨论】:

  • 我确实删除了它们,幸运的是,我没有粘贴所有的选择器代码。问题已经解决,在客户端。客户端也有一个选择器,以及一个要发送的消息列表。将消息添加到列表后,我调用 selector.wakeup(),但似乎如果消息很大,则选择器只写入第一个直到嵌套调用..
  • @Luo 这不是一个正确的分析。选择器不写任何东西。 write() 方法是写作的内容。你以为你写了一些东西,但你没有。
猜你喜欢
  • 2014-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-06
  • 2016-07-19
相关资源
最近更新 更多