SocketChannel.write(ByteBuffer[]) “损坏”数据

发布于 2024-10-28 01:01:37 字数 933 浏览 8 评论 0原文

问题: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。 。 欢迎任何帮助,感谢您的宝贵时间!

安德鲁

Problem: Corrupt TCP segment.

I send a sequence of ByteBuffers over and over in a SocketChannel. The sequence is the following:

\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)

...

I hope you see the pattern. The MTU on network level is about 1500, so it'll create TCP segments to send over the "chunk data".

The problem in the segments is: Somehow(?), randomly(?), a segment (its payload) starts with \r\n instead of the remaining bytes from the "chunk data" first.

So you get for example:

(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

Instead of:

(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

I'd like to know if Java code is even able to cause that, knowing that my "chunk data" ByteBuffer sent correctly, except for the ByteBuffer containing \r\n that joins in...
Any help is welcome, thank you for your time!

Andrew

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

二货你真萌 2024-11-04 01:01:37

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

I will bet that you are ignoring the result of a read or write. TCP does not lose or corrupt data and neither do the Socket APIs or the Java networking libraries. At least I've never seen it in about 22 years of network programming and 14 years of Java.

黯然#的苍凉 2024-11-04 01:01:37

这不是因为网络问题,而是因为我们的编码方式。如果我们以块的形式读取和写入数据,则可能会因最后一个块而导致数据损坏。最后读取的数据块可能已部分填充,并且字节数组的默认值为 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;
}

It is not because of network issue but with the way we coded. If we are reading and writing the data in chunks it may lead to data corruption because of last chunk. It may be possible the last data chunk read is partially filled and having default values as 0 for byte array.
Following example shows the solution for it

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();

And the method

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;
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文