2013-04-25 36 views
0

我的目標是發送不同類型的消息從客戶端到服務器,它將基於文本。我不確定的是如何在這裏刪除部分讀取。我必須確保我得到一個完整的信息,而不是更多。爪哇尼奧部分閱讀

有沒有人有這方面的經驗?

這是我到目前爲止有:

private void handleNewClientMessage(SelectionKey key) throws IOException { 
    SocketChannel sendingChannel = (SocketChannel) key.channel(); 

    ByteBuffer receivingBuffer = ByteBuffer.allocate(2048); 
    int bytesRead = sendingChannel.read(receivingBuffer); 
    if (bytesRead > 0) { 
     receivingBuffer.flip(); 

     byte[] array = new byte[receivingBuffer.limit()]; 
     receivingBuffer.get(array); 
     String message = new String(array); 

     System.out.println("Server received " +message);   
    } 
    selector.wakeup(); 
} 

但我沒有「結束」的消息的方式肯定有一個完整的消息。

最好的問候, Ø

+0

您應該在套接字上添加文本協議。像HTTP一樣。 – Nikolai 2013-04-25 14:40:19

+0

Hi @Nikolai。這聽起來不錯,你有鏈接到這裏的例子嗎?乾杯! – olemara 2013-04-30 08:02:46

+0

HTTP就是一個實際的例子。您可以使用HttpComponents庫來解析HTTP協議。 – Nikolai 2013-04-30 12:28:18

回答

3

你永遠不可能相信你不會讀超過一個消息,除非你一次只能讀一個字節。 (我不建議)。

相反,我會盡可能多地讀入ByteBuffer,然後解析它以查找消息的結尾,例如文本的換行符。

當您找到一行的結尾時,將其解壓縮並將其轉換爲字符串並對其進行處理。重複,直到你有一個部分的消息(或沒有剩下的東西)

如果你發現你只有一部分消息,你compact()(如果position()> 0),當你有和嘗試read()一些。

這將允許您儘可能多地讀取儘可能多的消息,但也可以處理不完整的消息。

注意:您需要保留ByteBuffer進行連接,以便您知道以前讀過的部分消息。

注意:如果您的郵件大於您的緩衝區大小,這將不起作用。我建議使用1+ MB的循環直接ByteBuffer。使用直接的ByteBuffers時,只有ByteBuffer所使用的頁面被分配給實際的內存。

如果您擔心性能,我會盡可能重新使用您的byte[]。如果您需要更多的空間,您只需要重新分配它。

順便說一句,你可能會發現,使用Plain IO的BufferedReader使用起來要簡單得多,但性能還是不錯的。

+0

嗨@Peter_Lawrey,謝謝你的好解釋。我會嘗試實施這種方法。 – olemara 2013-04-30 08:05:53