java - 从套接字输入流读取返回的数据顺序错误

标签 java sockets inputstream

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

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

最佳答案

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

从到 docs :

Reads up to len bytes of data from the input stream into an array of bytes. An attempt is made to read as many as len bytes, but a smaller number may be read. The number of bytes actually read is returned as an integer.

The first byte read is stored into element b[off], the next one into b[off+1], and so on. The number of bytes read is, at most, equal to len. Let k be the number of bytes actually read; these bytes will be stored in elements b[off] through b[off+k-1], leaving elements b[off+k] through b[off+len-1] unaffected.

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

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

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

关于java - 从套接字输入流读取返回的数据顺序错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10329437/

相关文章:

node.js - Socket.io在Ubuntu 16.04上不起作用

java - apache poi 4.0 条形图示例不起作用

java - 在android studio中看不到任何东西

java - 在 Java 中,如何将 InputStream 转换为字节数组 (byte[])?

c - 有没有办法告诉操作系统丢弃任何缓冲的传出 TCP 数据?

c - 使用 C 套接字将文件从服务器传输到客户端的问题

java - InputStream 缓冲数据

android - 将激光测距仪 (Bosch Disto GLM 50 C) 与智能手机 (Android Studio) 连接

java - 如何避免关闭传递给我包装在 Reader 流中的方法的 InputStream?

java - 有没有办法用输入来定义引脚?