COBS (Consistent Overhead Byte Stuffing)
Чтобы приёмник находил начало и конец сообщения в непрерывном потоке байтов, нужен разделитель, который никогда не встречается в данных. COBS делает таким разделителем байт 0x00 и платит за это предсказуемо: не больше одного лишнего байта на каждые 254 байта данных.
Обновлено Редакция GAW
COBS (Consistent Overhead Byte Stuffing) — алгоритм байт-стаффинга, который Стюарт Чешир и Мэри Бейкер опубликовали в 1999 году. Он перекодирует пакет так, что в нём не остаётся ни одного байта 0x00, и этот байт можно ставить в поток как границу кадра. Главное свойство — гарантированный худший случай: не больше одного лишнего байта на каждые 254 байта данных, то есть кодированный пакет не длиннее 100,4 % исходного.
Как кодирует
К пакету логически дописывают нулевой байт, после чего данные делят на куски, каждый из которых оканчивается нулём. Каждый кусок кодируется блоком: кодовый байт и следующие за ним байты данных без нуля. Кодовый байт говорит, сколько байтов данных идёт за ним (точнее, на единицу больше), а ноль в конце блока подразумевается. Отдельный случай — код 0xFF: 254 байта данных подряд без нуля, после которых ноль не вставляется.
Пример: данные 11 22 00 33 превращаются в 03 11 22 02 33, а в линию уходит 03 11 22 02 33 00 — последний ноль и есть граница кадра.
Сравнение со SLIP
| SLIP | COBS | |
|---|---|---|
| Разделитель | END = 0xC0 | 0x00 |
| Худший случай | пакет удваивается | +1 байт на 254 и разделитель |
| Лучший случай | +1–2 байта (END) | +1 байт кода и разделитель 0x00 |
| Буфер под кадр с разделителями | 2 × длина + 2 | длина + max(1, ⌈длина / 254⌉) + 1 |
Пустой пакет COBS кодирует одним кодовым байтом 01, и в линию уходит 01 00.
Cheshire и Baker сравнивают COBS именно с такими схемами: у SLIP, PPP и AX.25 средние накладные расходы малы, но худший случай — 200 %. Для микроконтроллера с маленьким буфером передачи предсказуемый размер удобнее.
Где применяют
COBS подходит для собственных протоколов поверх UART, USB CDC и радиоканалов, где нужно кадрирование без пауз по времени. Типичная структура кадра: данные, затем CRC, всё вместе кодируется COBS и завершается нулём. Приёмник накапливает байты до нуля, декодирует, проверяет CRC. Пошаговая реализация разборщика и сравнение способов кадрирования — в статье о реализации протоколов.
Частые вопросы
Чем COBS лучше SLIP?
Предсказуемым размером. В SLIP каждый байт, совпавший с разделителем или символом экранирования, превращается в два, и пакет из одних таких байтов удваивается. COBS по оценке Cheshire и Baker добавляет не больше одного байта на 254 — пакет растёт максимум до 100,4 % исходного, и буфер передатчика можно рассчитать заранее.
Можно ли декодировать COBS «на лету»?
Да. Приёмник читает кодовый байт, копирует следующие за ним байты данных, а в конце блока вставляет ноль (кроме блока с кодом 0xFF и последнего блока кадра). Встретив в потоке байт 0x00, он знает, что кадр закончился, и начинает новый — поэтому после сбоя синхронизация восстанавливается на ближайшем нуле.
Защищает ли COBS данные от ошибок?
Нет, COBS только кадрирует поток. Испорченный кодовый байт сдвинет разбор блоков, и кадр выйдет неверной длины или с нулём не на месте, но гарантии обнаружения ошибки это не даёт. Целостность проверяют CRC, который считают по данным до кодирования и передают вместе с ними.
Источники
- S. Cheshire, M. Baker. Consistent Overhead Byte Stuffing. IEEE/ACM Transactions on Networking, vol. 7, no. 2, April 1999 — аннотация: COBS в худшем случае добавляет не больше одного байта на 254, то есть кодированный пакет не больше 100,4 % исходного, против 200 % в худшем случае у многих алгоритмов байт-стаффинга (SLIP, PPP); разд. I: пакеты до 254 байт кодируются ровно с одним лишним байтом; разд. III: исключаемое значение — ноль, к пакету логически добавляется нулевой байт, данные делятся на фрагменты, оканчивающиеся нулём; блок кода — кодовый байт и следующие за ним байты данных, кодовый байт задаёт их число, за блоком подразумевается ноль; код 0xFF — 254 байта данных без нуля
- J. Romkey. RFC 1055: A Nonstandard for Transmission of IP Datagrams over Serial Lines: SLIP, 1988 — для сравнения: SLIP заменяет байт END двумя байтами ESC ESC_END, а ESC — двумя байтами ESC ESC_ESC, поэтому в худшем случае размер пакета удваивается
Нашли ошибку?
Смотрите также
- Реализация протокола обменаКадры по паузе, длине и разделителю, COBS, CRC-16, таймауты, разбор потока
- Байт-стаффингПерекодирование данных, чтобы разделитель кадра в них не встречался
- SLIPКадрирование по RFC 1055: разделитель END и экранирование ESC
- КадрированиеСпособы отделить сообщения друг от друга в непрерывном потоке байтов
- CRCЦиклический избыточный код для обнаружения ошибок
- UARTКадр 8N1, скорость и допуск, TX и RX, уровни, USB–UART, AVR и STM32