C : как читать и записывать многобайтовые целочисленные значения независимым от платформы способом?

#c #protocols #multibyte

#c #протоколы #многобайтовый

Вопрос:

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

Какой самый простой и быстрый способ чтения / записи многобайтовых значений независимым от платформы (т. Е. не зависящим от порядка байтов) способом?

Комментарии:

1. Многое можно сказать о тексте.

2. Просто не очень экономно занимает место, что, вероятно, имеет некоторые последствия для двоичного протокола.

3. Насколько большие значения? Произвольный размер или существует фиксированный предел? Подписанный или беззнаковый?

4. Выберите формат, не зависящий от платформы, а затем сохраните их в этом формате зависящим от платформы способом.

5. @DevSolar: Если пространство является фактором, то многое можно сказать в пользу использования универсального сжатия, после создания сообщения. Сбой, конечно, если вы отправляете много очень маленьких пакетов, но избавляет вас от необходимости придумывать другой продуманный краткий формат для каждого поля.

Ответ №1:

ФорматXDR может помочь вам в этом. Если бы мне пришлось обобщить это в одном предложении, это своего рода двоичный код UTF-8 для целых чисел.

Редактировать: Как упоминалось в моем комментарии ниже, я «знаю» XDR, потому что использую несколько функций, связанных с XDR, в своей офисной работе. Только после вашего комментария я понял, что формат «packed XDR», который я использую каждый день, даже не является частью официальных документов XDR, поэтому я опишу его отдельно.

Таким образом, идея:

  • проверьте наиболее значимый бит байта.
    • Если значение равно 0, этот байт является значением.
    • если это 1, следующие три бита дают «количество байтов», то есть количество байтов в значении.
      • замаскируйте верхнюю часть (бит флага плюс количество байтов), объедините соответствующее количество байтов, и вы получите значение.

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

Комментарии:

1. XDR интересен, но его минимальный размер значения составляет 4 байта, поэтому я не получаю никакой экономии пространства.

2. @Jen: Ого … только сейчас я понимаю, что формат «упакованного XDR», реализованный коллегой, по-видимому, не является частью официальной документации XDR…

Ответ №2:

Вас могут заинтересовать следующие функции:

htonl, htons, ntohl, ntohs — преобразование значений между порядком байтов на хосте и в сети

    uint32_t htonl(uint32_t hostlong);
   uint16_t htons(uint16_t hostshort);
   uint32_t ntohl(uint32_t netlong);
   uint16_t ntohs(uint16_t netshort);
  

man byteorder

Комментарии:

1. Не знаю, был ли в ваших словах сарказм («….»), но если нет, рад помочь! 🙂

2. Если серьезно, это решает проблему с порядковым номером стандартизированным способом (более сложная часть моей проблемы) — спасибо!

Ответ №3:

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

  • указание длины
  • конечный маркер

Вы, очевидно, объединяете их с некоторыми битами значений.

  • Для указания длины, которое дало бы вам что-то, где длина и некоторые биты указаны вместе (см., Например, UTF-8),

  • В качестве конечного маркера вы можете, например, указать, что MSB set указывает последний байт и, таким образом, имеет 7 бит данных на байт.

Очевидно, возможны другие варианты.

Ответ №4:

Вы могли бы попробовать сетевой порядок байтов

Ответ №5:

Буферы протокола Google предоставляют готовую реализацию, использующую кодировки переменной ширины.

Комментарии:

1. Да, буферы протокола — отличное решение. Я принимаю ответ DevSolar из-за простоты моего варианта использования.