Сетевые сообщения TCP могут быть фрагментированы. Но фрагментированные сообщения трудно разобрать, особенно когда передаются типы данных, превышающие байты. Например, buffer.getLong()
может потерпеть неудачу, если некоторые байты long
, я ожидаю, вернутся во второй буфер.Можно ли удалить фрагментацию TCP с помощью трубки?
Анализ был бы намного проще, если бы несколько каналов могли быть объединены на лету. Поэтому я решил отправить все данные через java.nio.channels.Pipe
.
// count total length
int length = 0;
foreach (Buffer buffer: buffers) {
length += buffer.remaining()
}
// write to pipe
Pipe pipe = Pipe.open();
pipe.sink().write(buffers);
// read back from pipe
ByteBuffer complete = ByteBuffer.allocateDirect(length)
if (pipe.source().read(complete) != length) {
System.out.println("Fragmented!")
}
Но это будет гарантировать полное заполнение буфера? Или Труба может снова ввести фрагментацию? Иными словами, будет ли тело состояния достигнуто?
Использование того же буфера будет самой простой стратегией. Но когда длина сообщения неизвестна до тех пор, пока в потоке не появится символ завершения, я не могу заранее назначить буфер и вынужден отложить выделение нового буфера, как только первый будет заполнен. – XZS
Когда TCP фрагментирует сообщение, он может фрагментироваться после любого байта, также между «длинным», нажатым на поток. Вот почему 'getLong()' может завершиться ошибкой с 'BufferUnderflowException', если' long' не был полностью получен. – XZS
@XZS Вы знаете, что такое сообщение максимальной длины, верно? Я не знаю, что ваш второй комментарий должен сказать мне, что я еще не знаю, за исключением того, что он доказывает, что вы не можете использовать два буфера, потому что «длинный» может быть разделен между ними. Основная проблема заключается в том, что вы должны продолжать чтение в том же буфере, пока не получите все, что вам нужно, а затем проанализируйте его. – EJP