1

问题:损坏的 TCP 段。

我在 SocketChannel 中一遍又一遍地发送一系列 ByteBuffer。顺序如下:

\r\n
length of chunk (example: fff)
\r\n
chunk data (rubbish, a 1000 - 5000 character long string)
\r\n
length of next chunk (example: fff)
\r\n
next chunk data (rubbish, a 1000 - 5000 character long string)

...

我希望你能看到模式。网络级别的 MTU 约为 1500,因此它将创建 TCP 段以通过“块数据”发送。

段中的问题是:不知何故(?),随机(?),段(其有效负载)以 \r\n 开头,而不是首先来自“块数据”的剩余字节。

所以你得到例如:

(segment 1)
\r\n
length of chunk (example: fff)
\r\n
chunk data (456 bytes)

(segment 2)
\r\n
chunk data (remaining 156 bytes)
length of next
\r\n

代替:

(segment 1)
\r\n
length of chunk (example: fff)
\r\n
chunk data (456 bytes)

(segment 2)
chunk data (remaining 156 bytes)
\r\n
length of next
\r\n

我想知道 Java 代码是否甚至能够导致这种情况,知道我的“块数据”ByteBuffer 发送正确,除了包含 \r\n 的 ByteBuffer 加入...欢迎任何帮助,谢谢您的时间!

安德鲁

4

2 回答 2

3

我敢打赌,您忽略了读取或写入的结果。TCP 不会丢失或损坏数据,Socket API 或 Java 网络库也不会。至少我在大约 22 年的网络编程和 14 年的 Java 中从未见过它。

于 2011-03-30T23:23:22.290 回答
0

这不是因为网络问题,而是因为我们编码的方式。如果我们以块的形式读取和写入数据,则可能由于最后一个块而导致数据损坏。最后一次读取的数据块可能被部分填充,并且字节数组的默认值为 0。以下示例显示了它的解决方案

ObjectOutputStream out = new ObjectOutputStream(
                socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
//Something local returns DataInputStream from server
InputStream dataInputStream = local.downloadFile(fileToBeRead);
int chunkSize = 10000;
byte[] chunkByteArray = new byte[chunkSize];
int bytesRead = -1;
while ((bytesRead = dataInputStream.read(chunkByteArray)) != -1) {
    if (bytesRead < chunkSize) {
        System.out.println("Last Chunk is " + bytesRead);
        chunkByteArray = getLastChunkByteArray(bytesRead,chunkByteArray);
    }
    out.write(chunkByteArray);
}
            dataInputStream.close();

以及方法

private byte[] getLastChunkByteArray(int noOfBytesRead,
        byte[] partialFilledChunk) {

    byte[] lastChunk = new byte[noOfBytesRead];
    for (int i = 0; i < noOfBytesRead; i++) {
        lastChunk[i] = partialFilledChunk[i];
    }
    return lastChunk;
}

于 2013-04-26T18:01:57.700 回答