3. Канальный уровень В этой главе рассматриваются алгоритмы надежной и эффективной передачи данных между двумя соседними машинами. Под словом ?соседние? мы понимаем то, что эти машины физически соединены проводом. Под проводом мы будем понимать любую физическую среду передачи данных, для которой справедливо, что биты поступают получателю точно в той последовательности, в какой их послал отправитель. Эта, простая, на первый взгляд, задача при детальном рассмотрении оказывается весьма сложной, если учесть, что при передаче по каналу могут возникать ошибки, возникают задержки, которые могут вызывать дублирование данных, и т.д. 3.1. Проблемы, решаемые на уровне канала данных На уровне канала данных решается ряд проблем, присущих только этому уровню: реализация сервиса для сетевого уровня, объединение битов, поступающих с физического уровня в кадры, обработка ошибок передачи, управление потоком кадров и другие. Основная задача канального уровня - обеспечить сервис сетевому уровню по передаче и приему данных. Назначение этого сервиса - передать данные от процесса на сетевом уровне одной машины процессу на сетевой уровень другой машины. Как это происходит, показано на рисунке 3-1 (а). Фактически процесс передачи сложнее, что проиллюстрировано на рисунке 3-1 (b). Однако для простоты изложения мы будем придерживаться первой схемы. Рисунок 3-1. Передача данных - виртуальная (a), фактическая (b) Канальный уровень может обеспечивать различный сервис. Хотя этот сервис может варьироваться от системы к системе, есть три общих видов сервиса: 1.Сервис без уведомления и без соединения 2.Сервис с уведомлением и без соединения 3.Сервис с уведомлением и с соединением Сервис без уведомления и без соединения не предполагает, что до начала передачи должно быть установлено соединение, которое после передачи должно быть разорвано, что факт приема переданного кадра должен подтверждаться специальным сообщением. Если в результате помех на физическом уровне кадр будет потерян, то никаких попыток его восстановить на канальном уровне произведено не будет. Этот класс сервиса используется там, где физический уровень обеспечивает настолько высокую надежность при передаче, что потери кадров происходят редко и восстановление при потере кадров можно переложить на верхние уровни. Этот вид сервиса также применяют при передаче данных в реальном времени там, где лучше потерять часть данных, чем увеличить задержку при их доставке. Например, передача речи, видео изображения. Большинство ЛВС использует этот вид сервиса на канальном уровне. Следующий вид сервиса - сервис с уведомлением без соединения. В этом виде сервиса получение каждого посланного кадра должно быть подтверждено. Если подтверждения не пришло в течение определенного промежутка времени, то считают, что кадр не принят и должен быть послан опять. Этот вид сервиса используется в ненадежной физической среде передачи, например, беспроводной. Можно было бы, конечно, подтверждать не кадры, а все сообщение целиком на сетевом уровне. Однако это было бы невыгодно для больших сообщений. Например, если при передаче этих данных разрушалось бы 10-20% кадров, то повторная передача таких сообщений заняла бы больше времени, чем передача их отдельных фрагментов. Поэтому подтверждение на канальном уровне следует рассматривать как минимизацию затрат на передачу данных, а не необходимость. Наиболее сложный класс сервиса на канальном уровне - сервис с соединением и уведомлением. Этот класс сервиса предполагает, что до начала передачи между машинами устанавливают соединение и данные передают по этому соединению. Каждый передаваемый кадр нумеруется, и канальный уровень гарантирует, что он будет обязательно получен, причем только один раз, а также что все кадры будут получены в надлежащей последовательности. При сервисе без соединения этого гарантировать нельзя, потому что потеря подтверждения получения кадра приведет к его пересылке, что, в свою очередь, приведет к появлению нескольких идентичных кадров. Использование сервиса с соединением особенно полезно в том случае, когда канал образует СПД. Как мы уже видели, в СПД может быть достаточно сложная организация канала, при которой может происходить коммутация потоков данных самыми разными способами. Здесь полезно вспомнить структуру кадра в Х.25, рассмотренную в разделе 2.3. С точки зрения структуры, в Х.25 есть три вида кадров: с 3-битовым полем номера кадра, 7- и 12-битовым. Таким образом, в Х.25 предусмотрен сервис с соединением, причем, в зависимости от длины передаваемых данных, можно оптимизировать затраты на поддержку соединения. При сервисе с соединением и уведомлением передача данных разбивается на три этапа. На первом этапе устанавливают соединение: на обеих машинах инициируют переменные и счетчики, отслеживающие, кадры с какими номерами были приняты, а с какими нет. На втором этапе передают нужные кадры. На третьем - соединение разрывают: переменные, счетчики, буферы и другие ресурсы, использованные для поддержки соединения, освобождают. На рисунке 3-2 показан типичный фрагмент WAN, где два маршрутизатора соединены через телефонную линию. Когда кадр поступает на маршрутизатор, аппаратура проверяет контрольную сумму и передает кадр канальному уровню. Канальный уровень проверяет, является ли поступивший кадр ожидаемым, и если да, то передает пакет, расположенный в кадре, сетевому уровню на другой машине. Рисунок 3-2. Размещение протокола канального уровня Сервис, создаваемый канальным уровнем для сетевого уровня, опирается на сервис, создаваемый физическим уровнем. На физическом уровне принимают и передают потоки битов. Отправленное количество битов не обязательно должно быть равно принятому количеству битов, значение посланного бита также не обязательно должно быть равно принятому значению бита. Поэтому на канальном уровне нужны специальные действия по обнаружению и исправлению таких ошибок. Типовой подход к решению подобных проблем - разбиение потока битов на кадры, подсчет контрольной суммы для каждого кадра и передача этой суммы вместе с кадром данных. При приеме контрольная сумма вычисляется для каждого кадра заново и сравнивается с той, что хранится в кадре. Если они различаются, то это признак ошибки передачи. На канальном уровне должны быть приняты меры к исправлению ошибки, например, сбросить плохой кадр и послать сообщение об ошибке тому, кто прислал этот кадр. Разбиение потока битов на кадры - задача не простая. Один из способов - делать паузу между битами разных кадров. Однако в сети, где нет единого таймера, нет гарантии, что эта пауза всегда будет одинаковой, или, наоборот, не появится новая пауза там, где ее не должно было быть. Так как методы, использующие временные задержки, не надежны, применяются другие методы. Здесь мы рассмотрим четыре основных метода: 1.счетчик символов 2.вставка специальных стартовых и конечных символов 3.вставка стартовых и концевых битов 4.нарушение кодировки на физическом уровне Первый метод показан на рисунке 3-3. В начале каждого кадра указывают, сколько символов в кадре. При приеме кадра вновь подсчитывают число принятых символов. Если число полученных символов отлично от ожидаемого числа, то этот факт воспринимают как ошибку. Однако этот метод имеет существенный недостаток: счетчик символов может быть искажен при передаче. Тогда принимающая сторона не сможет обнаружить границы кадра. Даже обнаружив несовпадение контрольных сумм, принимающая сторона не сможет сообщить передающей, какой кадр надо переслать и сколько символов пропало. Этот метод сейчас используется редко. Рисунок 3-3. Поток символов: (а) без ошибок; (b) с одной ошибкой Второй метод построен на вставке специальных символов. Обычно для этого используют последовательность символов DLE STX для начала кадра и DLE ETX для конца кадра. DLE (Data Link Escape), STX (Start TeXt), ETX (End TeXt) - это специальные символы, имеющие специальную кодировку. При этом методе, если даже была потеряна граница текущего кадра, нужно просто найти ближайшую последовательность DLE STX или DLE ETX. Однако здесь есть одна опасность: при передаче чисел или программы в объектном коде такие последовательности могут уже содержаться в передаваемых данных. Для решения этой проблемы используют прием экранирования: каждая последовательность DLE или STX просто дублируется в передаваемых данных. Поэтому, если при приеме есть два последовательных DLE, то один удаляется. Этот метод проиллюстрирован на рисунке 3-4. Рисунок 3-4. Метод экранирования Основным недостатком только что рассмотренного метода является то, что он жестко связан с размером байта и конкретным методом кодировки символов - ASCII. По мере развития сетей эта связь становилась все более и более обременительной. Кроме этого, на стороне отправителя надо было просматривать кадр, чтобы обнаружить недопустимые последовательности. Был предложен иной прием, позволяющий использовать любое число битов на символ и любую кодировку. Его идея состоит в том, что каждый кадр начинается и заканчивается специальным флаг-байтом: 01111110. Чтобы избежать аналогичной последовательности, внутри кадра поступают следующим образом. Посылающая сторона, встретив последовательно 5 единиц, обязательно вставит 0. Принимающая сторона, приняв 5 последовательных единиц, обязательно удалит следующий за ними 0. Таким образом, если в передаваемых данных встретится конфигурация флаг-байта, то она будет преобразована в конфигурацию 011111010. Этот метод иллюстрирует рисунок 3-5. Этот метод прозрачен для сетевого уровня так же, как и метод вставки байтов. Рисунок 3-5. Замена шестой единицы нулем Таким образом, кадр легко может быть распознан по флаг-байту. Если граница очередного кадра по какой-то причине была потеряна, то все что надо делать - ?ловить? ближайший флаг-байт. Последний метод - нарушение кодировки используется там, где применяется специальная кодировка битов на физическом уровне. Например, пусть для передачи одного бита используется два импульса. ?1? кодируется как переход ?высокое-низкое?, ?0? - как переход ?низкое-высокое?. Сочетания ?низкое-низкое? или ?высокое-высокое? не используются для передачи данных. Их и используют для границ кадра. Так делают в стандарте IEEE 802 для ЛВС, который мы рассмотрим позже. На практике используют, как правило, комбинацию этих методов. Например, счетчик символов с одним из выше перечисленных. Тогда, если число символов в кадре совпадает с кодировкой границы кадра, кадр считается переданным правильно. 3.1.3. Обнаружение ошибок Решив проблему разбиения на кадры, мы приходим к следующей проблеме: как обеспечить, чтобы кадры попадали на сетевой уровень в надлежащей последовательности? Если для отправляющей стороны все равно, в какой последовательности поступают кадры, то этой проблемы нет. Например, если нам нужен сервис без уведомления и без соединения. Однако как быть, если нам нужен сервис с уведомлением и с соединением? Для решения этой проблемы устанавливают обратную связь между отправителем и получателем в виде кадра подтверждения. Если кадр-подтверждение несет положительную информацию, то считается, что переданные кадры прошли нормально, если же в нем сообщение об ошибке, то переданные кадры надо передать заново. Однако возможны ситуации, когда из-за ошибок в канале кадр исчезнет целиком. В этом случае получатель не будет никак реагировать, а отправитель будет сколь угодно долго ждать подтверждения. Для решения этой проблемы на канальном уровне вводят таймеры. Когда передается очередной кадр, то одновременно устанавливается таймер на определенное время. Этого времени должно хватать на то, чтобы получатель получил кадр и отправил уведомление, а отправитель получил его. Если отправитель не получит уведомление раньше, чем истечет время, установленное на таймере, то он будет считать, что кадр потерян и повторит его еще раз. Однако если кадр-подтверждение был утерян, то вполне возможно, что один и тот же кадр получатель получит дважды. Как быть? Для решения этой проблемы каждому кадру присваивают порядковый номер. С помощью этого номера получатель может обнаружить дубли. Итак, таймеры и нумерация кадров - основные средства на канальном уровне, обеспечивающие доставку каждого кадра до сетевого уровня в единственном экземпляре и в нужном порядке. 3.1.4. Управление потоком Другая важная проблема, которую надо решать на канальном уровне - управление потоком. Вполне может случиться, что отправитель будет посылать кадры столь часто, что получатель не будет успевать их обрабатывать. Это может произойти, если, например, машина-отправитель более мощная или загружена слабее, чем машина-получатель. Для борьбы с такими ситуациями вводят специальный механизм управления потоком. Этот механизм предполагает обратную связь между отправителем и получателем, которая позволяет им урегулировать темп передачи. Существует много схем управления потоком, но все они в основе своей используют следующий сценарий. Прежде чем отправитель начнет передачу, он спрашивает у получателя, сколько кадров тот может принять. Получатель сообщает ему определенное число. Отправитель, после того как передаст это число кадров, должен приостановить передачу и спросить у получателя еще раз, сколько кадров тот может принять, и т.д. Позднее на примерах мы познакомимся с конкретными механизмами управления потоком. 3.2. Обнаружение и исправление ошибок При рассмотрении физической среды мы отмечали, что у беспроводных систем связи и аналоговых каналов, например, абонентской линии в телефонных сетях, достаточно высокий уровень ошибок в канале. Поэтому ошибки при передаче на физическом уровне - это реальность, которую надо обязательно учитывать. В разных средах характер ошибок разный. Ошибки могут быть одиночные, а могут возникать группами, сразу по несколько штук. У групповых ошибок есть свои достоинства и недостатки. Достоинство заключается в следующем. Пусть данные передаются блоками по 1000 бит, а частота ошибки - 10-3 на бит, т.е. одна на каждые 1000 бит. Если ошибки изолированные и независимые, то практически каждый блок в среднем будет содержать ошибку. Если же они возникают группами по 100 сразу, то ошибки будут содержать в среднем 1-2 блока из каждых 100. Недостатком групповых ошибок является то, что их труднее обнаруживать и исправлять, чем одиночные. 3.2.1. Коды с исправлением ошибок Для надежной передачи кодов было предложено два основных метода. Первый - внести избыточность в форме дополнительных битов в передаваемый блок данных так, чтобы, анализируя полученный блок, можно было бы указать, где возникли искажения. Это так называемые коды с исправлением ошибок. Второй метод - внести избыточность, но лишь настолько, чтобы, анализируя полученные данные, можно было сказать: есть в переданном блоке ошибки или нет. Это так называемые коды с обнаружением ошибок. Пусть данные занимают m разрядов, и мы добавляем r избыточных, контрольных разрядов. Нам необходимо передать слово длины n = m+r, которое называют n-битовым кодословом. Пусть у нас есть два кодослова - 10001001 и 10110001. С помощью операции EXCLUSIVE OR легко определить число различных разрядов в двух кодословах. В данном случае таких разрядов 3. Количество разных битов в двух кодословах называется расстоянием Хемминга между этими словами. Поэтому, если два кодослова находятся на расстоянии d по Хеммингу, это значит, что надо преобразовать ровно d разрядов, чтобы преобразовать одно кодослово в другое. В силу того, что избыточные контрольные разряды могут принимать только вполне определенные значения, то не все 2n кодовых слов возможны. Зная алгоритм установки контрольных разрядов, мы можем вычислить   минимальное расстояние по Хеммингу между двумя правильными кодословами.      Способен код исправлять ошибки или только обнаруживать их - зависит от расстояния между кодословами по Хеммингу. Если мы хотим обнаруживать d ошибок, то необходимо, чтобы два кодослова отстояли друг от друга на расстоянии d+1. Тогда, если принятый код отстоит на расстоянии k