我正在通过套接字发送字节数组。发送的数据以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个字节,然后是第四个数据包的整个数据,第二个数据包的最后一部分(从“最后一个数据包的长度”开始)和第三个数据包的整个数据。按此顺序。
有没有人知道可能导致此问题的原因?
答案 0 :(得分:2)
您读取字节数组的逻辑不太正确:
从docs:
将输入流中最多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;