2015-05-03 45 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