Любой хороший совет для форматирования пакетов TCP? - PullRequest
2 голосов
/ 22 марта 2009

Я создаю приложение для мобильного телефона, которое отправляет измерения ускорения через TCP-соединение на сервер.

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

В начале я отправляю строку в следующем формате:

##measurementTime#AccelerationX#AccelerationY#AccelerationZ

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

Я думал о XML, но он добавляет большую нагрузку, которую я, конечно, хотел бы избежать (измерения отправляются каждые 100-250 мс).

Ответы [ 5 ]

4 голосов
/ 23 марта 2009

Я бы хотел опираться на Ответ InSciTek Джеффа . Это то, что более широко известно как кодировка длины тега-значения . По идее, первый код - это тег , он говорит вам, как интерпретировать значение. Второй код - length , который сообщает, сколько байтов содержится в значении. Это отличный способ сделать расширяемое двоичное кодирование и часто используется в кодировании MPEG.

Я бы добавил еще несколько советов / требований по хорошему функциональному двоичному протоколу:

  1. включает номер версии в каждом сообщении, в котором указывается версия протокола для сообщения
  2. кодирует каждое многобайтовое поле в сетевой порядок байтов
  3. внимательно рассмотрите размер каждого поля
  4. рассмотрите возможность использования многобайтовой схемы кодирования для целых чисел: я не могу найти хорошую ссылку, но идея в том, что старший бит равен 1, если есть больше байтов, и 0, если это последний байт и младшие семь биты в каждом байте содержат значение.
  5. упаковывает все в провод в байтах и ​​никогда не структурирует

Первый действительно важен. Более важно, чтобы вы планировали изменения и тщательно решали, как изменится протокол. Клиенты никогда не должны пытаться интерпретировать сообщение, если они не поддерживают номер версии. НИКОГДА!

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

Если вы разрабатываете и внедряете протокол с учетом этих принципов, это сделает вашу жизнь намного проще, когда вам придется поддерживать и расширять ее. Последнее, что я очень рекомендую, - это написать диссектор для чего-то вроде Wireshark для вашего протокола. Это также упростит развертывание, тестирование и поддержку. Просто убедитесь, что вы полностью понимаете возможные юридические последствия написания такого диссектора, а также его развертывания, прежде чем рассматривать его.

2 голосов
/ 22 марта 2009

Одной из рекомендаций является отправка простых пар имя / значение, если вам необходимо полностью придерживаться потока текстового типа ASCII. Имя ключа используется для описания имени поля, которое каждое значение передает аналогично исходному предложению:

##keyName1=value1#keyName2=value2#

В качестве альтернативы, вы можете отправлять данные в двоичном теговом формате, например:

<tagCodeNum><lengthInBytes><tagValueAsBytes>

где tagCodeNum - это, возможно, байт или слово, а длина - это байт или слово, в зависимости от ваших потребностей. Идея этого формата заключается в том, что получатель может распознавать поля, которые он понимает, по номеру кода, а затем может также пропустить теги, которые он не знает, как декодировать. Таким образом, кодирование становится расширяемым. Если вам нужно сгруппировать несколько тегов в логические сообщения, я бы обернул группу этих двоичных кодированных тегов в общую иерархию сообщений:

<messageCodeNum><lengthInBytes><tag><tag><tag>

Если тег выше является копией предыдущей конструкции тега, описанной выше, а длина описывает длину в байтах всех тегов, объединенных вместе.

Примечание: Если вы думаете об этой структуре, она не сильно отличается от структуры типа XML, но она намного более краткая и ограниченная, так что ее почти тривиально декодировать.

1 голос
/ 22 марта 2009

Я бы искренне рекомендовал изменить структуру пакета на двоичный формат, если вы хотите уменьшить размер, это также позволит легко масштабировать в зависимости от того, как вы разграничиваете свои пакеты.

Вы можете сделать что-то в следующем порядке:

n байт начало + размер
время байта n
2-8 байт х
2-8 байт у
2-8 байт z

0 голосов
/ 23 марта 2009

Я думал о XML, но он добавляет много нагрузки

Вместо этого вы можете использовать JSON. Он не будет таким компактным, как двоичный формат, но гораздо более компактным, чем XML. И вы можете легко расширить формат данных.

0 голосов
/ 23 марта 2009

думает о чем-то оптимизированном:
- отправить только разницу с предыдущим значением;
- время от времени отправлять полный кадр;
- не используйте xml, создайте определение структуры;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...