2013-04-25 67 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