Согласованное заполнение байтов служебных данных

редактировать

Согласованное заполнение байтов служебных данных (COBS ) - это алгоритм для кодирования байтов данных, который приводит к эффективному, надежному и однозначному кадрированию пакета независимо от содержимого пакета, что упрощает для принимающих приложений восстановление после искаженных пакетов. Он использует конкретное значение байта, обычно ноль, чтобы служить разделителем пакета (специальное значение, которое указывает границу между пакетами). Когда ноль используется в качестве разделителя, алгоритм заменяет каждый нулевой байт данных ненулевым значением, чтобы в пакете не появлялись нулевые байты данных, и, таким образом, они были неверно интерпретированы как границы пакета.

Заполнение байтов - это процесс, который преобразует последовательность байтов данных, которые могут содержать «недопустимые» или «зарезервированные» значения (например, разделитель пакетов), в потенциально более длинную последовательность, которая не содержит повторений этих значений. Дополнительная длина преобразованной последовательности обычно упоминается как накладные расходы алгоритма. Алгоритм COBS жестко ограничивает накладные расходы наихудшего случая, ограничивая их минимум одним байтом и максимум ⌈n / 254⌉ байтами (один байт из 254, с округлением в большую сторону). Следовательно, время передачи закодированной последовательности байтов очень предсказуемо, что делает COBS полезным для приложений реального времени, в которых дрожание может быть проблематичным. Алгоритм является недорогим в вычислительном отношении, а его средние накладные расходы низки по сравнению с другими алгоритмами однозначного кадрирования.

COBS, однако, требует до 254 байтов опережающего просмотра. Перед передачей своего первого байта ему необходимо знать позицию первого нулевого байта (если есть) в следующих 254 байтах.

Содержание
  • 1 Кадрирование и заполнение пакетов
  • 2 Примеры кодирования
  • 3 Реализация
  • 4 Ссылки
  • 5 См. Также
  • 6 Внешние ссылки
Кадрирование и заполнение пакетов

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

COBS преобразует произвольную строку байтов в диапазоне [0,255] в байты в диапазоне [1,255]. После удаления всех нулевых байтов из данных, нулевой байт теперь можно использовать для однозначной отметки конца преобразованных данных. Это делается путем добавления нулевого байта к преобразованным данным, таким образом формируя пакет, состоящий из данных в кодировке COBS (полезная нагрузка ), чтобы однозначно обозначить конец пакета.

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

Процесс кодирования с последовательным заполнением байтов заголовка (COBS)

Существует два эквивалентных способа описания процесса кодирования COBS:

Описание блока с префиксом
Чтобы закодировать несколько байтов, сначала добавьте нулевой байт, затем разбейте их на группы по 254 ненулевых байта или 0–253 ненулевых байта, за которыми следует нулевой байт. Благодаря добавленному нулевому байту это всегда возможно.
Кодируйте каждую группу, удаляя конечный нулевой байт (если есть) и добавляя к началу числа ненулевых байтов плюс один. Таким образом, каждая закодированная группа имеет тот же размер, что и исходная, за исключением того, что 254 ненулевых байта кодируются в 255 байтов путем добавления байта 255 к началу.
В качестве особого исключения, если пакет заканчивается группой из 254 ненулевых байтов, нет необходимости добавлять завершающий нулевой байт. Это позволяет сэкономить один байт в некоторых ситуациях.
Описание связанного списка
Сначала вставьте нулевой байт в начало пакета и после каждого прогона 254 ненулевых байтов. Очевидно, что это кодирование обратимо. Нет необходимости вставлять нулевой байт в конец пакета, если он заканчивается ровно 254 ненулевыми байтами.
Во-вторых, замените каждый нулевой байт смещением на следующий нулевой байт, или конец пакета. Из-за дополнительных нулей, добавленных на первом шаге, каждое смещение гарантированно будет не более 255.
Примеры кодирования

Эти примеры показывают, как различные последовательности данных будут кодироваться алгоритмом COBS. В примерах все байты выражены как шестнадцатеричные значения, а закодированные данные показаны с текстовым форматированием, чтобы проиллюстрировать различные функции:

  • Жирный обозначает байт данных, который не был изменен кодированием. Все ненулевые байты данных остаются неизменными.
  • Зеленый цвет указывает на нулевой байт данных, который был изменен при кодировании. Все нулевые байты данных заменяются во время кодирования смещением на следующий нулевой байт (т. Е. Один плюс количество последующих ненулевых байтов). По сути, это указатель на следующий байт пакета, который требует интерпретации: если адресованный байт не равен нулю, то следующий байт данных нулевого байта заголовка группы указывает на следующий байт, требующий интерпретации; если адресный байт равен нулю, то это конец пакета.
  • Красный - это служебный байт, который также является байтом заголовка группы, содержащим смещение к следующей группе, но не соответствует байту данных. Они появляются в двух местах: в начале каждого закодированного пакета и после каждой группы из 254 ненулевых байтов.
  • Синий нулевой байт появляется в конце каждого пакета, чтобы указать конец пакета для приемник данных. Этот байт-ограничитель пакетов не является частью собственно COBS; это дополнительный байт кадра, который добавляется к закодированному выходу.
ПримерНезакодированные данные (шестнадцатеричный)Закодированные с помощью COBS (шестнадцатеричный)
10001 01 00
200 0001 01 01 00
311 22 00 3303 11 22 02 33 00
411 22 33 4405 11 22 33 44 00
511 00 00 0002 11 01 01 01 00
601 02 03... FD FEFF 01 02 03... FD FE 00
700 01 02... FC FD FE01 FF 01 02... FC FD FE 00
801 02 03... FD FE FFFF 01 02 03... FD FE 02 FF 00
902 03 04... FE FF 00FF 02 03 04... FE FF 01 01 00
1003 04 05... FF 00 01FE 03 04 05... FF 02 01 00

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

[ OHB]: служебный байт (начало кадра) 3+ -------------->| : Указывает на относительное расположение первого символа нуля 2 + -------->| : Нулевой байт данных, указывающий на следующий нулевой символ [EOP]: расположение нулевого символа конца пакета. 0 1 2 3 4 5: Позиция байта 03 11 22 02 33 00: Кадр данных COBS 11 22 00 33: Извлеченные данные OHB = Байт заголовка (указывает на следующий нулевой символ) EOP = Конец пакета

Примеры 7 по 10 показывают, как служебные данные меняются в зависимости от кодируемых данных для пакетов длиной 255 или более.

Реализация

Следующий код реализует кодировщик и декодер COBS на языке программирования C:

/ * * Байт StuffData заполняет байты «длины» * в месте, на которое указывает «ptr», записывая * вывод в место, указанное «dst». * * Возвращает длину закодированных данных. * / #include #include size_t StuffData (const uint8_t * ptr, size_t length, uint8_t * dst) {uint8_t * start = dst; uint8_t code = 1, * code_ptr = dst ++; / * Куда вставить начальный счетчик * / while (length--) {if (* ptr) / * Входной байт не равен нулю * / * dst ++ = * ptr, ++ code; if (! * ptr ++ || code == 0xFF) / * Ввод нулевой или полный блок * / * code_ptr = code, code = 1, code_ptr = dst ++; } * code_ptr = код; / * Окончательный код * / return dst - start; } / * * UnStuffData декодирует байты «длины» в * месте, на которое указывает «ptr», записывая * вывод в место, на которое указывает «dst». * * Возвращает длину декодированных данных * (которая гарантированно будет <= length). */ size_t UnStuffData(const uint8_t *ptr, size_t length, uint8_t *dst) { const uint8_t *start = dst, *end = ptr + length; uint8_t code = 0xFF, copy = 0; for (; ptr < end; copy--) { if (copy != 0) { *dst++ = *ptr++; } else { if (code != 0xFF) *dst++ = 0; copy = code = *ptr++; if (code == 0) break; /* Source length too long */ } } return dst - start; }
Ссылки
См. Также
Внешние ссылки
Последняя правка сделана 2021-05-15 10:10:32
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте