2015-05-03 31 views
1

我有一个带有选择器的NIO实现的服务器。 的实现是相当简单:Java 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()唤醒选择器,但它并没有帮助,因为问题与在处理第一条消息之后立即将密钥识别为“可读”有关。 有什么建议吗?

+0

nio的代码是出了名的难以得到完全正确。这是一个非常棘手的API。除非你被要求为一个类做这件事,否则我会使用像netty这样的框架来隐藏这种复杂性。 – jtahlborn

+0

选择器不会错过任何事件。你确定两个包真的到了吗? – EJP

回答

0

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

东西线沿线的:

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

我会删除它们,不幸的是,我粘贴的不是所有的选择器代码。 问题已解决,它在客户端。客户端也有一个选择器和一个要发送的消息列表。在向列表添加消息后,我调用了selector.wakeup(),但似乎如果消息很大,选择器只会写入第一个,直到嵌套调用。 – Luo

+1

@Luo这不是一个正确的分析。选择器不写任何东西。 'write()'方法是写什么的。你以为你写了一些东西,但没有。 – EJP