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

时间:2011-03-30 15:21:28

标签: java tcp segment

问题:损坏的TCP段。

我在SocketChannel中反复发送一系列ByteBuffers。顺序如下:

\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加入... 欢迎任何帮助,谢谢您的时间!

安德鲁

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分: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;
}