Э. Таненбаум, Д. Уэзеролл - Компьютерные сети (1114668), страница 71
Текст из файла (страница 71)
Процедуруstart_timer разрешается запускать во время работающего таймера. Такой вызов простопереинициализирует часы, чтобы можно было начать отсчет заново (до нового таймаута, если таковой будет иметь место).Процедуры start_ack_timer и stop_ack_timer используются для управления вспомогательными таймерами при формировании подтверждений в особых обстоятельствах.Процедуры enable_network_layer и disable_network_layer используются в более сложных протоколах, где уже не предполагается, что у сетевого уровня всегда есть пакетыдля отправки. Когда канальный уровень разрешает работу сетевого уровня, последний получает также разрешение прерывать работу первого, когда ему нужно послатьпакет. Такое событие мы будем обозначать как event=network_layer_ready. Когда сетевойуровень отключен, он не может инициировать такие события.
Тщательно следя завключением и выключением сетевого уровня, канальный уровень не допускает ситуации, в которой сетевой уровень заваливает его пакетами, для которых не осталосьместа в буфере.Последовательные номера кадров всегда находятся в пределах от 0 до MAX_SEQ(включительно). Число MAX_SEQ различно в разных протоколах. Для увеличения последовательного номера кадров на 1 циклически (то есть с обнулением при достижениичисла MAX_SEQ) используется макрос inc. Он определен в виде макроса, посколькуиспользуется прямо в строке в тех местах программы, где быстродействие являетсякритичным. Как мы увидим позднее в этой книге, производительность сети часто244 Глава 3.
Канальный уровень граничена быстродействием протоколов. Определение простых операций в видеомакросов не снижает удобочитаемости программы, увеличивая при этом ее быстродействие.Объявления в листинге 3.1 являются частью всех последующих протоколов. Дляэкономии места и удобства ссылок они были извлечены и собраны вместе, но, по идее,они должны быть объединены с протоколами.
В языке ��������������������������C�������������������������такое объединение производится с помощью директивы препроцессора #include с указанием ссылки на файлprotocol.h, в котором помещаются данные определения.3.3.1. Симплексный протокол «Утопия»В качестве первого примера мы рассмотрим самый простой протокол. Данные передаются только в одном направлении, и он даже не задумывается о том, что где-то можетпроизойти ошибка. Сетевой уровень на передающей и приемной стороне находитсяв состоянии постоянной готовности.
Временем обработки можно пренебречь. Размербуфера неограничен. И что лучше всего, канал связи между канальными уровнями никогда не теряет и не искажает кадры. Этот совершенно нереальный протокол, которыймы назовем «Утопия», показан в листинге 3.2. Он всего лишь демонстрирует базовуюструктуру, необходимую для построения настоящего протокола.Протокол состоит из двух процедур, sender1 (отправитель) и receiver1 (получатель). Процедура sender1 работает на канальном уровне посылающей машины,а процедура receiver1 — на канальном уровне принимающей машины.
Ни последовательные номера, ни подтверждения не используются, поэтому MAX_SEQ не требуется.Единственным возможным событием является frame_arrival (то есть прибытие неповрежденного кадра).Процедура sender1 представляет собой бесконечный цикл, начинающийся с оператора while, посылающий данные на линию с максимально возможной скоростью.
Телоцикла состоит из трех действий: получения пакета (всегда обязательное) с сетевогоуровня, формирования исходящего пакета с помощью переменной s и отсылки пакетаадресату. Из служебных полей кадра данный протокол использует только поле info,поскольку другие поля относятся к обработке ошибок и управлению потоком, которыев данном протоколе не применяются.Процедура принимающей стороны ничуть не сложнее.
Вначале она ожидает, покачто-нибудь произойдет, причем единственно возможным событием в данном протоколе может быть получение неповрежденного пакета. Когда пакет появляется, процедураwait_for_event возвращает управление, при этом переменной event присваиваетсязначение frame_arrival (которое все равно игнорируется).
Обращение к процедуреfrom_physical_layer удаляет вновь прибывший кадр из аппаратного буфера и помещает его в переменную r. Наконец, порция данных передается сетевому уровню,а канальный уровень отправляется ждать следующий кадр.Листинг 3.2. Неограниченный симплексный протокол «Утопия»/* Протокол 1 ("Утопия") обеспечивает только одностороннюю передачу данных — ототправителя к получателю.
Предполагается, что в канале связи нет ошибок и что получательспособен мгновенно обрабатывать получаемые данные. Соответственно, отправитель в циклепередает данные на линию с максимально доступной для него скоростью. */3.3. Элементарные протоколы передачи данных на канальном уровне 245typedef enum {frame_arrival} event_type;#include "protocol.h"void sender1(void){frame s;/* буфер для исходящего кадра */packet buffer;/* буфер для исходящего пакета */while (true) {from_network_layer(&buffer);s.info = buffer;to_physical_layer(&s);}/*/*/*/*получить у сетевого уровня пакет для передачи */скопировать его в кадр s для передачи */послать кадр s */Мы дни за днями шепчем "Завтра, завтра".Так тихими шагами жизнь ползетК последней недописанной странице.Макбет, V, v */}void receiver1(void){frame r;event_type event; /* заполняется процедурой ожидания событий, но не используется здесь*/while (true) {wait_for_event(&event); /* единственное возможное событие — прибытие кадра, событиеframe_arrival */from_physical_layer(&r);/* получить прибывший кадр */to_network_layer(&r.info);/* передать данные сетевому уровню */}0}Протокол «Утопия» абсолютно нереалистичен, так как он не умеет ни управлятьпотоком данных, ни исправлять ошибки.
Принцип его работы схож с сервисом безподтверждения и без установки соединения, который надеется, что все эти проблемырешаются на более высоких уровнях. Однако даже такой сервис все же обладает некоторыми способностями распознавать ошибки.3.3.2. Симплексный протокол с ожиданиемдля канала без ошибокТеперь мы отбросим самое нереальное предположение, использованное в протоколе 1, — способность получающего сетевого уровня мгновенно обрабатывать приходящие данные. Очень часто возникают ситуации, когда отправитель посылает данныеслишком быстро, и получатель не успевает обработать их.
Следовательно, очень важнопредотвращать такие заторы. Сохраняется предположение о том, что в канале связинет ошибок. Линия связи остается симплексной.Одно из решений — сконструировать получатель таким образом, чтобы его мощности хватало на обработку непрерывного потока последовательных кадров (или жеопределить канальный уровень так, чтобы информация пересылалась достаточномедленно, не вызывая перегрузки получателя). У получателя должен быть буфер246 Глава 3. Канальный уровеньбольшого объема, а его скорость должна быть не ниже скорости пересылки данных.Кроме того, он должен уметь быстро отдавать кадры сетевому уровню.
Это наихудшееиз возможных решений. Оно требует специального оборудования, и если линия загружена слабо, то ресурсы расходуются зря. Кроме того, он всего лишь перекладываетпроблему слишком быстрой пересылки кадров на чужие плечи: в данном случае ееприходится решать сетевому уровню.Лучшим решением данной проблемы является обратная связь со стороны получателя. Передав пакет сетевому уровню, получатель посылает небольшой управляющийпакет отправителю, разрешая тем самым посылать следующий кадр. Отправитель,отослав кадр, должен ждать разрешения на отправку следующего кадра.
Подобнаязадержка — это простейший пример протокола с управлением потоком.Протоколы, в которых отправитель посылает один кадр, после чего ожидает подтверждения, называются протоколами с ожиданием (stop-and-wait). В листинге 3.3приведен пример симплексного протокола с ожиданием.Листинг 3.3. Симплексный протокол с ожиданием/* Протокол 2 (с ожиданием) также обеспечивает только одностороннюю передачу данных, ототправителя к получателю. Снова предполагается, что в канале связи нет ошибок. Однакона этот раз емкость буфера получателя ограничена, и, кроме того, ограничена скоростьобработки данных получателем.
Поэтому протокол должен не допускать отправления данныхбыстрее, чем получатель способен их обработать. */typedef enum {frame_arrival} event_type;#include "protocol.h"void sender2(void){frame s;packet buffer;event_type event;/* буфер для исходящего кадра *//* буфер для исходящего пакета *//* единственное возможное событие — прибытие кадра(событие frame_arrival)*/while (true) {from_network_layer(&buffer);s.info = buffer;to_physical_layer(&s);wait_for_event(&event);/* получить у сетевого уровня пакет дляпередачи *//* скопировать его в кадр s для передачи *//* до свиданья, кадрик, до свиданья *//* не продолжать, пока на это не будетполучено разрешения */}}void receiver2(void){frame r, s;event_type event;/* буферы для кадров *//* frame_arrival является единственнымвозможным событием */while (true) {wait_for_event(&event); /* единственное возможное событие —прибытие кадра (событие frame_arrival)*/3.3. Элементарные протоколы передачи данных на канальном уровне from_physical_layer(&r);to_network_layer(&r.info);to_physical_layer(&s);247/* получить прибывший кадр *//* передать данные сетевому уровню *//* передать пустой кадр, чтобы разбудитьотправителя */}}Хотя пересылка данных в этом примере осуществляется по симплексному принципу, только от отправителя получателю, кадры в действительности путешествуютв обоих направлениях.
Следовательно, коммуникационный канал между двумя канальными уровнями должен поддерживать пересылку информации в обе стороны.Однако данный протокол диктует строгое чередование направлений пересылки:сначала отправитель посылает кадр, затем получатель посылает кадр, потом сноваотправитель, потом получатель и т. д. Для такой реализации хватило бы полудуплексного физического канала.Как и в протоколе 1, отправитель в начале цикла работы получает пакет от сетевогоуровня, формирует из него кадр и отправляет кадр по линии связи. Однако теперь,в отличие от протокола 1, отправитель должен ждать прибытия кадра с подтверждением, прежде чем он пойдет на следующую итерацию цикла и обратится к сетевомууровню за следующим пакетом.