Запись протокола потока: поле размера сообщения или разделитель сообщений? - PullRequest
11 голосов
/ 26 июня 2009

Я собираюсь написать протокол сообщения, проходящий через поток TCP. Получатель должен знать, где находятся границы сообщения.

Я могу отправить 1) сообщения фиксированной длины, 2) поля размера, чтобы получатель знал, насколько велико сообщение, или 3) уникальный терминатор сообщения (я полагаю, его нельзя использовать где-либо еще в сообщении).

Я не буду использовать № 1 по соображениям эффективности.

Мне нравится # 2, но возможно ли, чтобы поток вышел из синхронизации?

Мне не нравится идея № 3, потому что она означает, что получатель не может заранее знать размер сообщения, а также требует, чтобы терминатор не появлялся в другом месте сообщения.

В # 2, если возможно выйти из синхронизации, могу ли я добавить терминатор или я гарантированно никогда не выйду из синхронизации, если программа отправителя верна в том, что она отправляет? Нужно ли делать # 2 И # 3?

Пожалуйста, дайте мне знать.

Спасибо, JBU

Ответы [ 6 ]

5 голосов
/ 26 июня 2009

Вы используете TCP, доставка пакетов надежна. Таким образом, соединение либо обрывается, время ожидания или вы прочитаете все сообщение. Таким образом, вариант № 2 в порядке.

3 голосов
/ 04 июля 2010

Я согласен с sigjuice. Если у вас есть поле размера, нет необходимости добавлять и разделитель конца сообщения - Однако это хорошая идея. И то, и другое делает вещи намного надежнее и проще в отладке.

Попробуйте использовать стандартный формат строки netstring , который включает в себя как поле размера, так и символ конца строки. Поскольку в нем есть поле размера, в конце сообщения можно использовать символ конца строки.

3 голосов
/ 26 июня 2009

В зависимости от уровня, на котором вы работаете, # 2 может фактически не иметь проблем с выходом из синхронизации (TCP имеет порядковую нумерацию в пакетах и ​​собирает поток в правильном порядке для вас, если он выходит порядка).

Таким образом, # 2, вероятно, ваш лучший выбор. Кроме того, знание размера сообщения на ранней стадии передачи облегчит распределение памяти на принимающей стороне.

2 голосов
/ 09 октября 2012

Интересно, здесь нет однозначного ответа. № 2 безопасен по TCP, несмотря ни на что, и делается «в реальном мире» довольно часто. Это связано с тем, что TCP гарантирует, что все данные поступают как без повреждений, так и в том порядке, в котором они были отправлены, поэтому вероятность того, что правильная реализация может быть нарушена, отсутствует.

1 голос
/ 26 июня 2009

Если вы разрабатываете код передачи и получения с нуля, не мешало бы использовать как заголовки длины, так и разделители. Это обеспечит надежность и обнаружение ошибок. Рассмотрим случай, когда вы просто используете # 2. Если вы записываете поле длины N в поток TCP, но в итоге отправляете сообщение, которое имеет размер, отличный от N, принимающая сторона не будет знать ничего лучше и в конечном итоге запутается.

Если вы используете оба # 2 и # 3, хотя и не защищенный от ошибок, получатель может иметь большую степень уверенности в том, что он получил сообщение правильно, если он встретит разделитель после потребления N байтов из потока TCP. Вы также можете безопасно использовать разделитель внутри вашего сообщения.

Взгляните на HTTP Chunked Transfer Coding , чтобы получить реальный пример использования и № 2, и № 3.

0 голосов
/ 04 июля 2010

Существует четвертая альтернатива: протокол с самоописанием, такой как XML.

...