Добавлять или не дополнять - создание протокола связи - PullRequest
2 голосов
/ 17 июня 2009

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

Например: я хочу отправить заголовок сообщения, состоящий из 3-байтового поля, за которым следует 1-байтовое поле заполнения для 32-битного выравнивания. Затем я отправлю сообщение поверх данных.

В этом случае получатель просто возьмет 3 байта из потока и выбросит заполненный байт. А затем начните читать данные сообщения. На мой взгляд, он не будет хранить 3 байта и данные сообщения так, как он хочет. Весь смысл выравнивания байтов таков, что он будет получен эффективным способом. Но если ретривер не заботится о заполнении, как оно будет эффективно извлечено?

Без дополнения ретривер просто берет 3 байта заголовка из потока и затем получает байты данных. Поскольку ретривер хранит эти байты по своему усмотрению, какое это имеет значение, будет ли выполнено заполнение или нет?

Может быть, я упускаю точку заполнения.

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

Пожалуйста, дайте мне знать, что вы, ребята, думаете.

Спасибо, JBU

Ответы [ 5 ]

2 голосов
/ 17 июня 2009

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

Если я получатель, я мог бы передать буфер (то есть массив байтов) драйверу протокола (то есть стек TCP) и сказать: «верните это мне, когда в нем есть данные».

То, что я (приложение) получаю обратно, это массив байтов, который содержит данные. Используя трюки в стиле C, такие как «приведение» и т. Д., Я могу обрабатывать части этого массива, как если бы это были слова и двойные слова (а не только байты) ... при условии, что они выровнены надлежащим образом (что может быть дополнением) требуется).

Вот пример оператора, который читает DWORD из смещения в байтовом буфере:

DWORD getDword(const byte* buffer)
{
  //we want the DWORD which starts at byte-offset 8
  buffer += 8;
  //dereference as if it were pointing to a DWORD
  //(this would fail on some machines if the pointer
  //weren't pointing to a DWORD-aligned boundary)
  return *((DWORD*)buffer);
}

Вот соответствующая функция в сборке Intel; обратите внимание, что это один код операции, то есть достаточно эффективный способ доступа к данным, более эффективный, чем чтение и накопление отдельных байтов:

mov eax,DWORD PTR [esi+8]
2 голосов
/ 17 июня 2009

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

Если сообщение представляет собой поток байтов, например, xml, то заполнение не принесет вам много пользы.

Что касается разработки проводного протокола, вам, вероятно, следует рассмотреть возможность использования простого текстового протокола со сжатием (включая заголовок), который, вероятно, будет использовать меньшую пропускную способность, чем любой двоичный протокол, разработанный вами вручную.

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

Если у вас есть 3-байтовый заголовок и выровняете его по 4 байта, то обозначьте неиспользуемый байт как «зарезервированный для будущего использования» и потребуйте, чтобы биты были равны нулю (отклоняя сообщения, если они не так искажены). Это оставляет вам некоторую расширяемость. Или вы можете решить использовать байт в качестве номера версии - сначала ноль, а затем увеличивать его, если (когда) вы вносите несовместимые изменения в протокол. Не позволяйте значению быть «неопределенным» и «пофиг»; вы никогда не сможете использовать его, если начнете таким образом.

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

Еще одна веская причина, по которой в TCP есть заполнение (которое, вероятно, к вам не относится), заключается в том, что оно позволяет выделенному оборудованию сетевой обработки легко отделять данные от заголовка. Поскольку данные всегда начинаются с 32-разрядной границы, легче отделить заголовок от данных при маршрутизации пакета.

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

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

Еще одна причина рассмотреть заполнение - сохранить пару битов в полях длины. То есть всегда кратное 4 или 8 сохраняет 2 или 3 бита вне поля длины.

...