Перейти к содержанию
    

Помогите правильно обработать байт-стаффинг

Коллеги, лет 20 назад делал подобную штуку,проблем не было, а сейчас что-то запутался,старею. Внешнее покупное изделие регулярно раз в секунду шлёт мне сообщения. В каждом сообщении может быть несколько блоков данных. В начале каждого блока стоит макер начала - байт 0х10, в конце маркер окончания, два байта 0х10 и 0х03. Если в отправляемом блоке данных попадается код 0х10 то он передаётся два раза. Я в принятом сообщении ищу маркеры начала и конца блока,блок копирую в промежуточный массив для разбора, а при копировании ищу два подряд стоящих 0х10 и один из них пропускаю. И так с каждым блоком. Работает, но примерно каждое десятое сообщение получаю битым. Подозреваю что иногда происходит неправильное определение начала и конца блока. Ведь если внутри блока попадётся пара 0х10 и 0х03 маркер конца будет определён неверно. На что следует обратить внимание?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, _sda said:

Ведь если внутри блока попадётся пара 0х10 и 0х03 маркер конца будет определён неверно. На что следует обратить внимание?

Внутри сообщения границы между блоками будут отмечены тройками:  0х10, 0х03 и 0x10..

Изменено пользователем blackfin
Опечатка..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вах, шайтан! Точно, только тройка будет 0х10, 0х03 и 0x10

Спасибо! Сейчас проверю.

p.s. А если в внутри блока будет такая тройка? У меня там время передаётся - 16 часов, 3 минуты 16 секунд. Кирдык.

Похоже нужно как то хитрее...

Походу нужно проверять не три байта а пять...

13 10 03 10 5C

Но Вы меня натолкнули на эту мысль, спасибо!

p.p.s. тогда как быть с последним блоком? Опять засада...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

26 minutes ago, _sda said:

А если в внутри блока будет такая тройка?

Эту ошибку не обойти никак. Можно только уменьшить вероятность её появления.

После вставки байта 0x10 комбинация 0x10, 0x03, 0x10 превратится в 0x10, 0x10, 0x03, 0x10, 0x10, что соответствует границе между блоками.

Можно, конечно, запретить такую комбинацию из пяти байт в качестве маркера конца блока, но тогда есть вероятность потерять границу блока который заканчивается на 0x10, в том случае, если следующий блок начинается с 0x10. В этом случае возникает комбинация из шести байт: 0x10, 0x10, 0x10, 0x03, 0x10, 0x10 которая как раз и соответствует маркеру окончания блока.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 минут назад, blackfin сказал:

Можно, конечно, запретить такую комбинацию из пяти байт в качестве маркера конца блока, но тогда есть вероятность потерять границу блока который заканчивается на 0x10, в том случае, если следующий блок начинается с 0x10. В этом случае возникает комбинация: 0x10, 0x10, 0x10, 0x03, 0x10, 0x10 которая как раз и соответствует маркеру окончания блока.

Согласен, увеличивая длину цепочки уменьшаем вероятность ложного обнаружения маркера.

11 минут назад, blackfin сказал:

Эту ошибку не обойти никак. Можно только уменьшить вероятность её появления.

А мне сейчас показалось что можно. Что если за критерий конца взять цепочку 0x10, 0x10, 0x10, 0x03 или 0x10, 0x03 с нечётным количеством байт 0х10 перед байтом 0х03? Что скажете?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

31 minutes ago, _sda said:

Что если за критерий конца взять цепочку 0x10, 0x10, 0x10, 0x03 или 0x10, 0x03 с нечётным количеством байт 0х10 перед байтом 0х03? Что скажете?

Похоже, что это правильное решение.. ;)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 минуты назад, blackfin сказал:

Похоже, что это правильное решение.. ;)

Какой я молодец:dirol:

Тогда и после 0х03 ничего проверять не нужно, последний блок нормально проверится.

Спасибо за диалог!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ага... Прямо по теме стаффинга: "Одна голова - хорошо, а две головы - хорошо-хорошо." ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, _sda сказал:

В начале каждого блока стоит макер начала - байт 0х10, в конце маркер окончания, два байта 0х10 и 0х03. Если в отправляемом блоке данных попадается код 0х10 то он передаётся два раза.

Какой-то странный и излишне сложный метод... А если в начале кадра данных будет идти 0x03? Тогда после кодирования это начало будет выглядеть как конец кадра.

Мне известно 3 основных способа кодонезависимого кодирования:

 

1. А-ля SLIP.

Выбираем два спец.значения символа == X и == Y. Где X - будет маркер конца, Y - код для экранирования спец.значений встретившихся в блоке данных. При кодировании кадр обрамляется в начале и в конце значением X, а если внутри блока данных встретится значение X или Y, то оно заменяется на пару Y,X1 или на пару Y,Y1 соответственно (где X1, Y1 - любые выбранные значения не равные X и не равные Y).

Если необходимо, то таким методом можно добавить бОльшее число спец.значений символов для целей управления в канале (например - для управления потоком). Все эти значения должны экранироваться символом Y.

Плюсы: Простота (проще других методов); лёгкая возможность добавления дополнительных спец.значений.

Минусы: Большая потенциальная избыточность в некоторых случаях.

 

2. Байт-стаффинг по типу бит-стаффинга.

Начало и конец кадра в канале маркируется последовательностью из N символов со значением == X. Если внутри блока данных встретится (N-1) символов со значением == X, то после них вставляется любое значение != X. В конце кадра (перед хвостовыми N символами X) также всегда вставляется любое значение != X (хотя другой способ: делать это только если при кодировании текущий счётчик символов X не равен 0).

Плюсы: В случае больших кадров данных, избыточность будет минимальной из всех методов.

Минусы: В случае маленьких кадров плюс превратится в минус.

 

3. COBS. https://ru.wikipedia.org/wiki/Вставка_байтов_с_фиксированной_избыточностью

COBS мне нравится больше всех. И если я не ограничен в выборе, то использую обычно его.

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

Минусы: Сложнее других методов.

 

Есть конечно еще всякие неоптимальные методы, типа представления в виде ASCII значений (MIME, UUENCODE и т.п.). Их не рассматриваю.

 

Любой из этих методов - кодонезависим. А значит включившись в любой момент в любую точку потока кодированных данных можно правильно выделить кадр данных из потока символов вне зависимости от его содержимого.

1 час назад, _sda сказал:

Что если за критерий конца взять цепочку 0x10, 0x10, 0x10, 0x03 или 0x10, 0x03 с нечётным количеством байт 0х10 перед байтом 0х03? Что скажете?

Так всё-таки Вы создаёте что-то своё и нет необходимости в совместимости с готовым устройством, работающим в конкретном кодировании?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1).Я в топе сказал что принимаю данные из покупного изделия. Что имеем то имеем...

2).Протокол организован так, что первым байтом 0х03 никогда не будет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 минут назад, _sda сказал:

1).Я в топе сказал что принимаю данные из покупного изделия. Что имеем то имеем...

Понятно. Всё равно - кривоватый метод. Он даже не кодонезависимый. Ибо - включившись в любой произвольный момент в поток кодированных данных, невозможно однозначно определить границы кадра и правильно декодировать кадр из потока. Придётся применять дополнительные методы валидации кадра.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, это оно. Куда я смотрел... Тут английским по белому всё написано про odd...

Столько времени потерял.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...