ЭКРАНИРОВАНИЕ БАЙТОВ В ПОСЛЕДОВАТЕЛЬНОЙ СВЯЗИ
Как разделитель может одновременно быть данными?
Последовательный приёмник распознаёт символы, а приложение должно выделять сообщения. SLIP экранирует C0 и DB в полезной нагрузке двухбайтовыми последовательностями, чтобы неэкранированный END мог обозначать границу пакета. Приёмник выполняет обратное преобразование, сохраняя своё состояние между операциями чтения. Эти конкретные значения относятся к SLIP и сами по себе не обеспечивают проверку ошибок или безопасность.
Символ и пакет
Одна лишь граница символа не позволяет выделить сообщение приложения.
Экранирование специальных значений в данных
SLIP представляет специальные байты полезной нагрузки двухбайтовыми последовательностями.
Сохранение состояния
Анализатор должен сохранять состояние экранирования, даже если операция чтения заканчивается на DB.
Обозначьте конечные точки и область защиты.
Уточните фактический протокол и настройки.
Проведите разрешённое испытание с безвредными данными.
Контрольный список выбора и проверки — развернуть
Уточните протокол и уровень захвата; протестируйте обычные и специальные байты; проверьте чтение по частям, повторяющиеся маркеры и обработку ошибок в среде, где у вас есть разрешение на такие действия.
Последовательная линия передаёт поток байтов. Как принимающая программа узнаёт, где заканчивается сообщение? Один из подходов — зарезервировать маркер. Но данные измерения или файл могут содержать байт с тем же значением, и его передача без изменений может быть ошибочно воспринята как признак окончания. Экранирование байтов устраняет эту неоднозначность. Чтобы понять его работу, следует различать приём символов, границы пакетов и смысл данных для приложения, а не рассматривать только скорость передачи в бодах.

Правильно принятые символы не образуют пакет автоматически
В типичном асинхронном последовательном интерфейсе для выделения символа используются стартовый бит, биты данных и стоповые биты. Поступившие в программу символы образуют последовательность байтов. Приёмник не узнаёт автоматически, где начинается и заканчивается показание температуры. Определение границ символов и границ полных сообщений — разные задачи.
Для выделения сообщений прикладной протокол может использовать фиксированную длину, поле длины, временные интервалы или специальные маркеры. У каждого способа есть свои условия применения и компромиссы. В этой статье SLIP используется как простой пример формирования кадров при последовательной передаче для объяснения маркеров и экранирования. Это не означает, что каждый последовательный протокол использует SLIP или что существующий протокол можно менять без тщательного рассмотрения.
Однопортовый сервер последовательных устройств Feichang FCT-1100-F1S1 с интерфейсом «три в одном» служит реальным примером связи между последовательным интерфейсом и сетью. Байты, пересылаемые через интерфейс или сеть, не приобретают автоматически нового прикладного смысла. В статье не делаются выводы о внутреннем протоколе формирования кадров этого изделия; его фактические возможности следует уточнять по документации и настройкам.
Почему один маркер может выполнять две роли
Предположим, обе стороны договорились, что определённый байт обозначает конец. Получив его, анализатор передаёт далее предшествующие данные, накопленные в буфере. Это похоже на знак препинания, обозначающий конец предложения. Однако двоичные данные могут содержать байт с любым значением; ни одно выбранное значение не исключается из полезной нагрузки автоматически.
Запись измерения может содержать то же значение, что и маркер конца. Должен ли анализатор считать такое вхождение данными или границей? По одному лишь значению определить это невозможно. Отправителю и приёмнику нужно общее правило, изменяющее представление специальных значений в линии передачи.
Простой запрет какого-либо значения ограничивает возможное содержимое исходных данных и может незаметно изменить результаты измерений. Замена медной линии оптоволоконной также не устраняет неоднозначность: оптическое преобразование меняет среду передачи, но не интерпретацию данных прикладным протоколом. Качество линии связи и правила кодирования необходимо проверять отдельно.
Экранирование меняет представление, а не данные
Экранирование можно рассматривать как указание интерпретировать следующий байт по согласованному правилу. Отправитель проверяет полезную нагрузку и заменяет значения байтов, требующие экранирования, специальными последовательностями. Приёмник выполняет обратное преобразование и должен получить то же исходное содержимое.
В примере SLIP, описанном в RFC 1055, шестнадцатеричное значение C0 обозначает END, а DB — ESC. C0 внутри полезной нагрузки заменяется на DB DC, а DB — на DB DD. Неэкранированный C0 обозначает фактическую границу конца пакета. Эти конкретные значения относятся к данному примеру, а не ко всем последовательным протоколам.
Зачем экранировать ещё и DB? Этот байт задаёт специальную интерпретацию следующего байта. Если исходный DB передать без отличительного представления, следующее обычное значение может быть ошибочно воспринято как суффикс экранирующей последовательности. Экранирование как разделителя, так и байта начала экранирования позволяет избежать новой неоднозначности.

Проследим короткий пример от отправителя до приёмника
Возьмём исходную полезную нагрузку 11 C0 22 DB 33. Два специальных значения нельзя напрямую поместить в поток кадров как обычные данные. После кодирования получается 11 DB DC 22 DB DD 33; результат ограничивается настоящими маркерами END, чтобы приёмник мог отличить управляющие элементы от восстановленных данных.
На этой иллюстрации C0 расположен и перед пакетом, и после него. В RFC 1055 рассматривается передача END в начале как способ сбросить накопленные помеховые данные; результат нулевой длины, возникающий из-за последовательных маркеров, не следует передавать далее как обычный пакет IP. В других протоколах не обязательно используются одинаковые маркеры с обеих сторон.
После декодирования C0 и DB из полезной нагрузки снова становятся обычными данными. Сами разделители не входят в передаваемое приложению содержимое. Кодирование может увеличить число байтов в линии передачи. Показания счётчиков сервера последовательных устройств, данные захвата и длины на уровне приложения могут различаться при измерении на разных уровнях, и это само по себе не доказывает потерю данных.
Приёмник должен помнить своё текущее состояние
Анализатор не всегда может обрабатывать каждый байт независимо от остальных. Он должен как минимум различать обычное чтение и ожидание суффикса после байта начала экранирования. В обычном состоянии END обозначает границу пакета, а DB переводит анализатор в состояние ожидания суффикса вместо немедленной выдачи DB как исходных данных.
В состоянии ожидания приёмник применяет согласованное преобразование и возвращается в обычное состояние. Связь между двумя байтами сохраняется благодаря состоянию анализатора; байтам не обязательно поступать в рамках одной программной операции чтения. Если одна операция чтения заканчивается на DB, а следующая начинается с DC, приёмник должен сохранить состояние и завершить преобразование.
В реальной реализации также необходимы правила для недопустимых суффиксов, ограничений буфера, пустых пакетов и прерываний. Эта статья не задаёт единой универсальной стратегии обработки ошибок. Если программа сбрасывает состояние анализатора при каждой операции сетевого чтения или считает каждую такую операцию отдельным сообщением, выделение кадров может нарушиться, даже если транспорт доставил все байты.

Граница — не проверка ошибок и не гарантия безопасности
Экранирование устраняет неоднозначность представления. Оно не добавляет автоматически обнаружение ошибок, повторную передачу, аутентификацию или шифрование. Разбиение потока на пакеты не доказывает, что каждый пакет корректен или что его отправителю можно доверять. Сам SLIP предоставляет ограниченный набор функций, и его не следует считать универсальным протоколом безопасности для систем промышленного управления.
Разные протоколы также могут выполнять проверки и экранирование на разных этапах. HDLC-подобное формирование кадров PPP имеет собственные правила использования флага, обеспечения прозрачности передачи и проверки кадров; эти детали не совпадают с SLIP. Смешение значений маркеров, суффиксов экранирования или этапов проверки может привести к тому, что обе стороны получают байты, но ни одна не принимает пакет.
Определите, где находятся исходные данные приложения, где выполняются кодирование, физическая или сетевая передача, декодирование и проверка на уровне приложения. При исследовании ошибок определите уровень наблюдения, прежде чем сравнивать ожидаемое содержимое. Прямое побайтовое сравнение закодированного трафика с декодированными полями приложения может создать видимость неисправности, которой нет.
Проверяйте согласованность правил на небольших воспроизводимых примерах
Начните с документации на устройство и протокол. Зафиксируйте версии, настройки интерфейса, правила формирования пакетов и точки захвата. Протестируйте обычные данные, данные со значением конца, данные со значением экранирования и последовательные специальные значения. Проверьте как закодированную, так и декодированную форму. Это примеры методов, а не утверждение о проведении измерений на конкретном изделии.
Затем протестируйте чтение по частям, объединение данных в одной операции чтения и разрывы соединения там, где реализация должна их обрабатывать. Используйте безвредные данные в среде, где у вас есть разрешение на такие действия; не отправляйте байты из примеров как команды в действующую производственную систему. Если конечные устройства используют разные протоколы, выясните, кто выполняет преобразование, прежде чем многократно менять скорость передачи в бодах.
Помните об уровнях: UART выделяет символы, правило формирования кадров выделяет сообщения, а экранирование не позволяет принять специальные значения полезной нагрузки за управляющие маркеры. Такое разделение объясняет, почему порт может получать байты, а приложение при этом не может восстановить полное сообщение.
Первоисточники
RFC 1055: SLIP, июнь 1988, не является стандартом Интернета; RFC 1662: PPP с HDLC-подобным формированием кадров, июль 1994. Изделие в контексте статьи: сервер последовательных устройств FCT-1100-F1S1; это не означает, что оно использует SLIP.
Переведено с китайской технической статьи: Прочитать оригинальную статью на китайском языке.
Частые практические вопросы
Позволяет ли приём символов по последовательному интерфейсу автоматически выделить пакет?
Нет. Приём символов UART и формирование кадров на уровне приложения — разные задачи; обеим сторонам нужны одинаковые правила формирования кадров.
Как SLIP экранирует C0 и DB в полезной нагрузке?
C0 в полезной нагрузке заменяется на DB DC, а DB — на DB DD; неэкранированный END обозначает границу. Другие протоколы могут использовать иные правила.
Заменяет ли экранирование байтов проверку целостности или шифрование?
Нет. Оно устраняет неоднозначность между управляющими маркерами и значениями полезной нагрузки, но не обеспечивает автоматически обнаружение ошибок, повторную передачу, аутентификацию или шифрование.
Область рассмотрения и дополнительные материалы
Обобщённый пример формирования кадров SLIP, а не утверждение о конкретном изделии или результатах измерений.
Полузакрытие TCP и ответы последовательного интерфейса · Единичные нагрузки RS485 и допустимая нагрузка передатчика


