Как разделить сообщения в бинарном сетевом потоке?

Я кодирую, отправляю и декодирую данные, используя sockets/networkStream. Но как я могу эффективно отделить сообщения друг от друга?

Например, когда я использую 1024-байтовый буфер, я получаю данные через networkStream. Затем я хочу передать этот буфер моему классу декодера, но я не уверен, что часть следующего сообщения уже скрывается в буфере. Если мое сообщение имеет только 50 байтов, как я узнаю, что в этом буфере нет 20 сообщений? Или, что еще хуже, в моем буфере могут быть частичные сообщения?

Допустим, мое сообщение имеет 3000 байт, может ли быть сообщение и начало второго сообщения в буфере? Или networkStream автоматически получает сообщения в пакетах по мере их отправки?


person pixartist    schedule 08.05.2012    source источник
comment
Ваш вопрос был похож на ваш стрим. Большой кусок данных и никаких терминаторов сообщений. Я представил \n\n в качестве терминатора в вашем вопросе.   -  person jgauffin    schedule 25.05.2012


Ответы (1)


Есть два общих варианта:

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

Все методы отправки двоичных данных переменного размера через сокет являются вариациями на одну из этих двух тем.

person Greg Hewgill    schedule 08.05.2012
comment
Отправьте заголовок фиксированного размера. Это очевидно, но, возможно, стоит повторить - person caesay; 08.05.2012
comment
@caesay, не обязательно. Вы можете использовать какой-то код переменной длины (например, один из кодов Элиаса). - person svick; 08.05.2012
comment
Есть и третий вариант: протокол с самоописанием, такой как XML. - person user207421; 08.05.2012
comment
@EJP: Возможно, но я бы посчитал это (растянутым) отклонением от второго. Каждое имя узла имеет символ завершения, и вообще все имеет какой-то индикатор завершения. - person caesay; 15.05.2012
comment
@caesay Я бы рассматривал это как третий вариант. «Окончание, которое не может появиться в сообщении», не является «самоописывающим протоколом». - person user207421; 15.05.2012
comment
Я бы не сказал, что XML — это то, что вы должны использовать для определения границ сообщения. Путь к сложному, так как вам нужно искать конец корневого узла (и допустимо иметь внутренний узел с тем же именем, что и корневой узел). Фиксированный заголовок, вероятно, самый простой способ. - person jgauffin; 25.05.2012