问题描述
我在解析缓冲区时遇到来自 Java 中 TCP 套接字的 InputStream 的问题:
InputStream stream = (InputStream)socket.getInputStream();
int numBytesReceived = 0;
byte[] receiveBuffer = new byte[20];
while(numBytesReceived != -1) {
numBytesReceived = 0;
numBytesReceived = stream.read(tempReceive);
// Code to start reading bytes from the receiveBuffer and parse into messages here
}
假设我们从缓冲区解析的每条消息都包含一个标头字节,指示消息中数据的大小(以字节为单位),其余为数据字节。
从上面的代码来看,receiveBuffer 被分配了 20 字节。下面是一个例子: [2,1,3,4,0]
- 一条消息的头部为 2,有 2 个数据字节 [2,1]
- 第二条消息包含 3 个标头,因此 3 个数据字节 [3,1]
- 第三条消息包含 4 个标头,因此 4 个数据字节 [4,1]
缓冲区的其余部分只是 0。这很好,直到用户开始发送大量数据包,因此 receiveBuffer 可能如下所示:
[2,2,2]
本例中有6条消息,但第6条消息被截断。我的代码将尝试读取 2 个不存在的字节,并抛出 BufferUnderflowException。
我该怎么做才能确保在每个 read() 上一次读取我发送的所有消息?我不知道为什么它会切断消息。
如果我找到一种一次性获取所有字节的方法,那么它并不能真正避免用户一次发送数百到数千条消息,我将拥有一个非常大的缓冲区,因此我需要保留缓冲区大小受限(假设我每条消息最多发送 20 个字节)
解决方法
如果消息被截断(如果我们没有读完消息的所有字节),我已经设法通过在下一次循环迭代中继续 read() 来解决这个问题。
如果一条消息如示例中所示被截断,它会继续到下一个 read() 并且我只需要在解析它之前检查我之前是否正在阅读一条消息。