Недостаток такой системы в том, что при передаче может быть искажен сам счетчик. Например, если при подсчете байтов второго фрейма произойдет ошибка в единственном бите и число 5 превратится в 7, как показано на илл. 3.3 (б), то целевое устройство потеряет синхронизацию и не сможет правильно обнаружить начало следующего фрейма. Даже если контрольная сумма не сойдется (скорее всего) и устройство поймет, что фрейм принят неверно, то оно все равно не сможет определить начало следующего фрейма. Запрашивать повторную передачу фрейма бесполезно, поскольку неизвестно, сколько байтов нужно пропустить до начала повторной передачи. По этой причине на сегодняшний день метод подсчета байтов отдельно практически не применяется.
Илл. 3.3. Поток байтов: (а) без ошибок; (б) с одной ошибкой
Второй метод формирования фреймов решает проблему восстановления синхронизации после сбоя при помощи маркировки начала и конца каждого фрейма специальными байтами. Зачастую в качестве разделителя используется один и тот же байт, называемый флаговым (flag byte). Он устанавливается в начальной и конечной точке фрейма. Этот байт помечен на илл. 3.4 (а) как FLAG. Два соседних флаговых байта говорят о том, что закончился один фрейм и начался другой. Таким образом, если приемник теряет синхронизацию, ему необходимо просто найти два флаговых байта, с помощью которых он распознает конец текущего фрейма и начало следующего.
Однако одна проблема все же остается. В передаваемых данных, особенно если это двоичные данные (например, фотографии или музыка), запросто может встретиться последовательность, используемая в качестве флагового байта. Возникновение такой ситуации, скорее всего, собьет синхронизацию. Один из способов решения проблемы — добавление специального escape-символа (знака переключения кода, ESC) непосредственно перед случайно совпавшим флаговым байтом внутри фрейма. Таким образом, настоящий флаг можно отличить по наличию или отсутствию перед ним ESC. Канальный уровень получателя вначале убирает эти escape-символы, затем передает фрейм на сетевой уровень. Такой метод называется байт-стаффингом (byte stuffing).
Следующий логичный вопрос: а что, если и символ ESC случайно окажется в данных? Решение такое же: вставить перед фиктивным escape-символом настоящий. На стороне получателя первый символ ESC будет удален, а следующий байт данных останется, даже если это еще один байт ESC или флаговый байт. На илл. 3.4 (б) показаны некоторые примеры. В любом случае байтовая последовательность после ее очищения от вставленных символов в точности совпадает с исходной. Найти границу фрейма можно все так же по двум последовательным флаговым байтам до удаления дополнительных символов ESC.
Илл. 3.4. (а) Фрейм, ограниченный флаговыми байтами. (б) Четыре примера байтовых последовательностей до и после байт-стаффинга
Схема байт-стаффинга, представленная на илл. 3.4, — это немного упрощенная модель протокола PPP (Point-to-Point Protocol, протокол «точка-точка»), который служит для передачи пакетов по коммуникационным каналам и широко используется в сети интернет. Мы подробно обсудим протокол PPP в разделе 3.5.1.
Третий метод разделения потока битов на фреймы позволяет обойти недостатки байт-стаффинга, который обязывает использовать исключительно 8-битные байты. Делить данные на фреймы можно на уровне битов, причем фреймы могут содержать произвольное число битов и состоять из блоков любого размера. Данный метод был разработан для некогда популярного протокола HDLC (High-level Data Link Control — высокоуровневый протокол управления каналом передачи данных). Каждый фрейм начинается и завершается специальной последовательностью битов, 01111110 (или 0x7E в шестнадцатеричной системе). Это все тот же флаговый байт. Если в битовом потоке встретится пять единиц подряд, уровень передачи данных автоматически вставит в выходной поток нулевой бит. Бит-стаффинг (bit stuffing) аналогичен байт-стаффингу, при котором во фрейм вставляется escape-символ перед случайным флагом. Он также гарантирует минимальную плотность передачи, помогающую сохранять синхронизацию на физическом уровне. По этой причине бит-стаффинг применяется в протоколе USB.
Когда принимающая сторона встречает пять единиц подряд, за которыми следует ноль, она автоматически удаляет его. Бит-стаффинг, как и байт-стаффинг, является абсолютно прозрачным для сетевого уровня обоих устройств. Если флаговая последовательность 01111110 встречается в данных пользователя, она передается в виде 011111010, но в памяти целевого устройства сохраняется в исходном виде: 01111110. При этом вышележащие уровни остаются в полном неведении о применении бит-стаффинга. На илл. 3.5 приведен пример этого метода.
Илл. 3.5. Бит-стаффинг. (а) Исходные данные. (б) Данные на линии. (в) Данные, сохраненные в памяти после удаления вставленных битов