2012-04-26 31 views
0

我通过套接字发送字节数组。发送的数据以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个字节,然后返回第四个数据包的全部数据,第二个数据包的最后一部分(从“最后一个数据包的长度”开始)和第三个数据包的全部数据。按此顺序。

有没有人有线索可能会导致此问题?

回答

2

你的用于读出的字节阵列逻辑是不完全正确:

从到docs

读取最多len从输入流数据的字节到的 字节的数组。试图读取多达len字节,但可以读取较小的 数字。实际读取的字节数作为整数返回为 。

读出的第一个字节被存储到元素b [OFF],下通入 B [关+ 1],等等。读取的字节数最多等于 len。令k为实际读取的字节数;这些字节将是存储在元素b [off]至b [off + k-1]中的 ,通过b [off + len-1]不会影响元素 b [off + k]到b [off + len-1]。

然而,随着bytesRead变量保持为0的整个循环,从InputStream任何数据总是被写入到您的缓冲区的开头,已经覆盖数据在那里。

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

while ((bytesRead = inputStream.read(result, total - remaining, remaining)) != -1 
    && remaining > 0) { 
    remaining -= bytesRead; 
+0

非常感谢。你只是让我的一天(实际上整个下周):) – Francis 2012-04-26 09:45:34

+0

最后一段代码非常有用。忘记检查返回值很容易。这是一个简单的2线解决方案。 – user1132959 2013-05-13 04:50:51

相关问题