SocketChannel.write (ByteBuffer []) «портит» данные - PullRequest
1 голос
/ 30 марта 2011

Проблема: поврежден сегмент TCP.

Я посылаю последовательность ByteBuffers снова и снова в SocketChannel. Последовательность следующая:

\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 с "порциями" отправил правильно, за исключением ByteBuffer, содержащего \ r \ n, который присоединяется ... Любая помощь приветствуется, спасибо за ваше время!

Andrew

Ответы [ 2 ]

3 голосов
/ 31 марта 2011

Держу пари, что вы игнорируете результат чтения или записи. TCP не теряет и не портит данные, а также API-интерфейсы Socket или сетевые библиотеки Java. По крайней мере, я никогда не видел этого за 22 года сетевого программирования и 14 лет Java.

0 голосов
/ 26 апреля 2013

Это не из-за проблем с сетью, а из-за того, как мы кодировали.Если мы читаем и записываем данные порциями, это может привести к повреждению данных из-за последней порции.Возможно, что последнее чтение фрагмента данных частично заполнено и имеет значения по умолчанию, равные 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;
}

</p> <p>

...