При рассмотрении канального уровня пакет, передаваемый ему по интерфейсу сетевым уровнем, рассматривается как чистые данные, каждый бит которых должен быть доставлен сетевому уровню принимающей машины. Тот факт, что сетевой уровень принимающей машины может интерпретировать часть этого пакета как заголовок, не касается канального уровня.
Получив пакет, канальный уровень формирует из пакета кадры, добавляя заголовок и концевик (см. рис. 3.1). Таким образом, кадр состоит из внедренного пакета, некоторой служебной информации (в заголовке) и контрольной суммы (в концевике). Затем кадр передается канальному уровню принимающей машины. Мы будем предполагать наличие соответствующих библиотечных процедур, например tO_physical_layer для отправки кадра и from_physical_l ayer для получения кадра. Эти процедуры вычисляют и добавляют или проверяют контрольную сумму (обычно это делается аппаратно), так что протоколы, о которых мы говорим в этом разделе, могут не беспокоиться об этом. Они могут применять, например, алгоритм циклических кодов, обсуждавшийся в предыдущем разделе.
Вначале получатель ничего не должен делать. Он просто сидит без дела, ожидая, что что-то произойдет. В приводимых в данной главе примерах протоколов ожидание событий уровнем передачи данных обозначается вызовом процедуры wait_for_ event(&event). Эта процедура возвращает управление, только когда что-то происходит (например, прибывает кадр). При этом переменная event сообщает, что именно случилось. Наборы возможных событий отличаются в разных протоколах и поэтому будут описываться для каждого протокола отдельно. Следует заметить, что в действительности канальный уровень не находится в холостом цикле ожидания событий, как мы предположили, а получает прерывание, когда это событие происходит. При этом он приостанавливает свои текущие процессы и обрабатывает пришедший кадр. Тем не менее для простоты мы проигнорируем эти детали и предположим, что канальный уровень все свое время посвящает работе с одним каналом.
Листинг 3.1. Общие объявления для последующих протоколов. Объявления располагаются в файле protocol.h
Листинг 3.1
Когда принимающая машина получает кадр, контрольная сумма вычисляется заново. Если контрольная сумма в кадре неверна (то есть при передаче возникли ошибки), то канальный уровень получает соответствующую информацию (event=cksum_err). Если кадр прибывает в целости, канальному уровню об этом также сообщается (event=frame_arri val), после чего он может получить этот кадр у физического уровня с помощью процедуры from_physical_layer. Получив неповрежденный кадр, канальный уровень проверяет управляющую информацию, находящуюся в заголовке кадра, и если все в порядке, часть этого кадра передается сетевому уровню. Заголовок кадра не передается сетевому уровню ни при каких обстоятельствах.
Для запрета передачи сетевому уровню любой части заголовка кадра есть веская причина: поддержание полного разделения сетевого и канального уровней. До тех пор пока сетевой уровень ничего не знает о формате кадра и протоколе канального уровня, изменения формата и протокола не потребуют изменений программного обеспечения сетевого уровня. Это происходит при установке в компьютер новой сетевой карты. Поддержание строгого интерфейса между сетевым и канальным уровнями значительно упрощает разработку программ, так как протоколы различных уровней могут развиваться независимо.
В листинге 3.1 показаны некоторые объявления (на языке C), общие для многих протоколов, обсуждаемых ниже. Определены пять типов данных: boolean, seq_nr, packet, frame_kind и frame. Тип boolean представляет собой перечисляемый тип, переменные которого могут принимать значения true или false. Тип seq_nr является целым без знака, используемым для нумерации кадров. Эти последовательные номера могут принимать значения от 0 до числа MAX_SEQ включительно, которое определяется в каждом протоколе, использующем его. Тип packet является единицей информации, используемой при обмене информацией между сетевым и канальным уровнями одной машины или двумя равноранговыми сетевыми уровнями. В нашей модели пакет всегда состоит из MAX_PKT байт, хотя на практике он обычно имеет переменную длину.
Структура frame состоит из четырех полей: kind, seq, ack и info, первые три из которых содержат управляющую информацию, а последнее может содержать данные, которые необходимо передать. Эти три управляющих поля вместе называются заголовком кадра (frame header).