Java NIO ByteBuffer:在读取完整消息之前读取头上的消息大小

时间:2012-07-12 14:48:05

标签: size nio head bytebuffer socketchannel

我正在创建一个接收消息的java NIO服务器,每个消息的大小都在消息的头部,这就是为什么我先读入一个具有默认大小(44)的缓冲区,然后得到完整的大小从这个缓冲区,然后创建一个新的缓冲区,它应该获取消息的其余部分(正文),然后使用System.arrayCopy()创建一个包含完整消息的数组。这个操作运行良好,问题是第二个缓冲区(消息正文)有大小但不包含正确的数据。 如果你错了,这里是我的代码:

public void getMessageByMessageSize(SelectionKey key) {
    socket = (SocketChannel) key.channel();
    int nBytes = 0;
    byte[] message = null;
    try {
        nBytes = socket.read(headBuffer);
        if (nBytes < 0) {
            try {
                key.channel().close();
                key.cancel();
                return;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
                    //size of the message body
        int corpMessageSize = MessageUtils.getMessageSize(headBuffer)
                - HEADER_SIZE;
        ByteBuffer corpsBuffer = ByteBuffer.allocate(corpMessageSize);
        headBuffer.flip();
        nBytes += socket.read(corpsBuffer);
        corpsBuffer.flip();
        byte[] corp=corpsBuffer.array();

        message = new byte[nBytes];
        System.arraycopy(headBuffer.array(), 0, message, 0, HEADER_SIZE);
        System.arraycopy(corpsBuffer.array(), 0, message, HEADER_SIZE,
                nBytes - HEADER_SIZE);
        System.out.println(nBytes);
        headBuffer.clear();
        corpsBuffer.clear();
    } catch (IOException e) {
        e.printStackTrace();
        try {
            key.channel().close();
            key.cancel();
            return;
        } catch (IOException ex) {
            e.printStackTrace();
        }
    }

    this.worker.verifyConnection(this,message, key);
    //this.worker.processData(this, socket, message, nBytes);
}

我有一个简单的客户端发送创建一个字节消息,在头部发出它的大小,然后发送它。

感谢

1 个答案:

答案 0 :(得分:1)

  

nBytes + = socket.read(corpsBuffer);

您假设这会读取整个消息并填充缓冲区。 TCP / IP中没有任何内容可以保证这一点。你必须循环。如果您处于非阻塞模式,则必须重新选择是否获得零长度读取。