1

我正在通过套接字发送字节数组。发送的数据以 4 个字节开始,指示后续字节数组的长度。

// get the amount of data being sent
byte[] lengthOfReplyAsArray = new byte[4];
forceRead(inputStream, lengthOfReplyAsArray);
int lengthOfReply = byteArrayToInt(lengthOfReplyAsArray);

// read the data into a byte array
byte[] reply = new byte[lengthOfReply];
forceRead(inputStream, reply);

用于从 InputStream 读取数据的方法:

private byte[] forceRead(InputStream inputStream, byte[] result)
        throws IOException {

    int bytesRead = 0;
    int total = result.length;
    int remaining = total;

    while (remaining > 0)
        remaining -= inputStream.read(result, bytesRead, remaining);

    return result;

}

用于将字节数组转换为整数的方法:

private int byteArrayToInt(byte[] byteArray) {
    int result = 0;

    for (int i = 0; (i<byteArray.length) && (i<8); i++) {
        result |= (byteArray[3-i] & 0xff) << (i << 3);
    }
    return result;                  
}

问题是,数据不是按照到达的顺序读取的。前 4 个字节被读取得很好。其余的都混在一起了。我进行了 TCP 转储以确保数据正确到达客户端。似乎数据被分成 4 个 TCP 数据包。InputStream 返回第一个数据包的前 4 个字节,然后是第四个数据包的全部数据,第二个数据包的最后部分(从“最后一个数据包的长度”开始)和第三个数据包的全部数据。按照这个顺序。

有谁知道可能导致此问题的原因?

4

1 回答 1

2

您读取字节数组的逻辑不太正确:

文档

从输入流中读取最多 len 个字节的数据到一个字节数组中。尝试读取多达 len 个字节,但可能会读取较小的字节数。实际读取的字节数以整数形式返回。

读取的第一个字节存储在元素 b[off] 中,下一个字节存储在 b[off+1] 中,依此类推。读取的字节数最多等于 len。设 k 为实际读取的字节数;这些字节将存储在元素 b[off] 到 b[off+k-1] 中,而元素 b[off+k] 到 b[off+len-1] 不受影响。

但是,由于您的bytesRead变量在整个循环中保持为 0,因此输入流中的任何数据都始终写入缓冲区的开头,从而覆盖那里已经存在的数据。

什么会更好(检查 -1 还将确保如果流过早地用完数据会导致remaining增加,则不会从剩余中减去 -1,这意味着循环将不必要地运行,直到缓冲区溢出导致remaining消极的):

while ((bytesRead = inputStream.read(result, total - remaining, remaining)) != -1
     && remaining > 0) {
    remaining -= bytesRead;
于 2012-04-26T08:25:32.187 回答