Э. Таненбаум - Компьютерные сети. (4-е издание) (PDF) (1130118), страница 62
Текст из файла (страница 62)
Событие timeoutможет произойти, только если запущен таймер. Процедуру start_timer разрешается запускать во время работающего таймера. Такой вызов просто переинициализирует часы, чтобы можно было начать отсчет заново (до нового тайм-аута, если таковой будет иметь место).Процедуры start_ack_timer и stop_ack_timer используются для управлениявспомогательными таймерами при формировании подтверждений в особых обстоятельствах.Процедуры enable_network_layer и disable_network_layer используются в болеесложных протоколах, где уже не предполагается, что у сетевого уровня всегдаесть пакеты для отправки.
Когда уровень передачи данных разрешает работу сетевого уровня, последний получает также разрешение прерывать работу первого, когда ему нужно послать пакет. Такое событие мы будем обозначать какevent=network_layer_ready. Когда сетевой уровень отключен, он не может инициировать такие события.
Тщательно следя за включением и выключением сетевогоуровня, уровень передачи данных не допускает ситуации, в которой сетевой уровень заваливает его пакетами, для которых не осталось места в буфере.Последовательные номера кадров всегда находятся в пределах от 0 до МАХ_SEQ (включительно). Число MAX_SEQ различно в разных протоколах. Для увеличения последовательного номера кадров на 1 циклически (то есть с обнулением при достижении числа MAXJSEQ) используется макрос inc. Он определен ввиде макроса, поскольку используется прямо в строке в тех местах программы,где быстродействие является критичным.
Как мы увидим позднее в этой книге,производительность сети часто ограничена быстродействием протоколов. Определение простых операций в виде макросов не снижает удобочитаемости программы, увеличивая при этом ее быстродействие. К тому же, поскольку МАХ_SEQ в разных протоколах будет иметь разные значения, то, определив инкрементв виде макроса, можно один и тот же код без проблем использовать в несколькихпротоколах. Такая возможность крайне полезна для симулятора.244Элементарные протоколы передачи данныхГлава 3. Уровень передачи данныхОбъявления в листинге 3.1 являются частью всех последующих протоколов.Для экономии места и удобства ссылок они были извлечены и собраны вместе,но, по идее, они должны быть объединены с протоколами. В языке С такое объединение производится с помощью директивы препроцессора #include с указанием ссылки на файл protocol.h, в котором помещаются данные определения.Листинг 3 .
1 . Общие объявления для последующих протоколов. Объявлениярасполагаются в файле protocol.h#define MAX_PKT 1024typedeftypedef*/typedeftypedef/* определяет размер пакета в байтах */enum {false, true} boolean;unsigned int seqjir:/* тип boolean *//* порядковые номера кадров или подтвержденийНеограниченный симплексный протоколstruct {unsigned char data[MAX_PKT];} packet; /* определение пакета */enum {data, ack. nak} frante_kind: /* определение типа пакета */typedef struct {*/frame_kind kind;seqjir seq;seqjir ack;packet info;} frame;В качестве первого примера мы рассмотрим самый простой протокол. Данные передаются только в одном направлении.
Сетевой уровень на передающей и приемной сторонах находится в состоянии постоянной готовности. Временем обработки можно пренебречь. Размер буфера неограничен. И что лучше всего, каналсвязи между уровнями передачи данных никогда не теряет и не искажает кадры.Этот совершенно нереальный протокол, который мы назовем «утопия», показанв листинге 3.2.Протокол состоит из двух процедур, sender (отправитель) и receiver (получатель). Процедура sender работает на уровне передачи данных посылающей машины, а процедура receiver — на уровне передачи данных принимающей машины.Ни последовательные номера, ни подтверждения не используются, поэтому МАХ_SEQne требуется.
Единственным возможным событием является frame_arrival (тоесть прибытие неповрежденного кадра).Процедура sender представляет собой бесконечный цикл, начинающийся с оператора while, посылающий данные на линию с максимально возможной скоростью. Тело цикла состоит из трех действий: получения пакета (всегда обязательное)с сетевого уровня, формирования исходящего пакета с помощью переменной s иотсылки пакета адресату. Из служебных полей кадра данный протокол использует только поле info, поскольку другие поля относятся к обработке ошибок иуправлению потоком, которые в данном протоколе не применяются.Процедура принимающей стороны ничуть не сложнее.
Вначале она ожидает,пока что-нибудь произойдет, причем единственно возможным событием в данном протоколе может быть получение неповрежденного пакета. Когда пакет появляется, процедура wait_for_event возвращает управление, при этом переменнойevent присваивается значение frame_arriva1 (которое все равно игнорируется).Обращение к процедуре from_physi ca 1 _1 ауег удаляет вновь прибывший кадр изаппаратного буфера и помещает его в переменную г. Наконец, порция данныхпередается сетевому уровню, а уровень передачи данных отправляется ждать следующий кадр./* данный уровень занимается транспортировкой кадров/*/*/*/*245тип кадра */порядковый номер */номер подтверждения */пакет сетевого уровня *//* ожидать события и вернуть тип события в переменной event */void wait_for_event(event_type *event):/* получить пакет у сетевого уровня для передачи по каналу */void from_network_layer(packet * p ) ;/* передать информацию из полученного пакета сетевому уровню */void to_network_layer(packet * p ) ;/* получить пришедший пакет у физического уровня и скопировать его в г */void from_physical_layer(frame * r ) ;/* передать кадр физическому уровню для передачи */void to_physical_layer(frame * s ) ;/* запустить таймер и разрешить событие timeout */void start_timer(seqjir k);/* остановить таймер и запретить событие timeout */void stop_timer(seq_nr k ) ;/* запустить вспомогательный таймер и разрешить событие ack_timeout */void start_ack_timer(void):/* остановить вспомогательный таймер и запретить событие ack timeout */void stop_ack_timer(void);Листинг 3.2.
Неограниченный симплексный протокол/* разрешить сетевому уровню инициировать событие network_layer_ready */void enable_network_layer(void):/*• Протокол 1 (утопия) обеспечивает только одностороннюю передачу данных - ототправителя к получателю. Предполагается, что в канале связи нет ошибок и чтополучатель способен мгновенно обрабатывать получаемые данные. Соответственно,отправитель в цикле передает данные на линию с максимально доступной для негоскоростью. *//* запретить сетевому уровню инициировать событие network layer ready */void disable_network_layer(void):/* макрос inc развертывается прямо в строке: Циклически увеличить переменную к */fdefine inc(k) if (к < MAX SEQ) к = к + 1; else к = 0typedef enum {frame_arrival} event_type:A246Глава 3. Уровень передачи данныхЭлементарные протоколы передачи данных#include "protocol.h"void senderl(void){frame s;packet buffer;while (true) {from_network_layer(&buffer);*/s.info = buffer;to_physical_1ayer(&s):При некоторых обстоятельствах (например, при синхронной передаче, когдауровень передачи данных принимающей машины обрабатывает всего одну входную линию) может быть достаточно всего лишь вставить задержку в передающуюпрограмму протокола 1, снизив скорость его работы настолько, чтобы уберечьпринимающую сторону от забивания данными.
Однако в реальных условияхобычно каждый уровень передачи данных должен одновременно обрабатыватьнесколько линий, и время, необходимое на обработку одного кадра, может меняться в довольно значительных пределах. Если разработчик сети может рассчитать наихудшую ситуацию для приемника, он может запрограммировать настолько медленную работу отправителя, что даже при самой медленной обработкепоступающих кадров получатель будет успевать их обрабатывать. Недостатоктакого подхода в его консерватизме.
В данном случае использование пропускнойспособности будет намного ниже оптимального уровня. Исключением может бытьтолько один случай — когда время реакции принимающего уровня передачи данных изменяется очень незначительно.Лучшим решением данной проблемы является обратная связь со стороны получателя. Передав пакет сетевому уровню, получатель посылает небольшой управляющий пакет отправителю, разрешая тем самым посылать следующий кадр.
Отправитель, отослав кадр, должен ждать разрешения на отправку следующего кадра.Протоколы, в которых отправитель посылает один кадр, после чего ожидаетподтверждения, называются протоколами с ожиданием. В листинге 3.3 приведен пример симплексного протокола с ожиданием./* буфер для исходящего кадра *//* буфер для исходящего пакета *//* получить у сетевого уровня пакет для передачи/* скопировать его в кадр s для передачи *//* послать кадр s *//* Мы дни за днями шепчем «Завтра, завтра».Так тихими шагами жизнь ползетК последней недописанной странице.- Макбет. V, v */void receiverl(void){frame r;event_type event; /* заполняется процедурой ожидания событий, но не используетсяздесь */while (true) {wait_for_event(&event); /* единственное возможное событие - прибытие кадра,событие frame_arrival */from_physical_layer(&r):/* получить прибывший кадр */to_network_layer(&r.info);/* передать данные сетевому уровню */Листинг 3.3. Симплексный протокол с ожиданием/* Протокол 2 (с ожиданием) также обеспечивает только одностороннюю передачу данных.от отправителя к получателю.