Шрифт:
}
}
Илл. 3.12. Неограниченный симплексный протокол «Утопия»
Протокол «Утопия» абсолютно нереалистичен, так как он не способен ни управлять потоком данных, ни исправлять ошибки. Он напоминает службу без подтверждения и без установки соединения, которая надеется, что все эти проблемы решаются на более высоких уровнях. Однако даже такая служба обладает некоторыми способностями распознавать ошибки.
Добавляем управление потоком: протокол с остановкой и ожиданием
Усложним задачу: предположим, отправитель посылает данные слишком быстро и получатель не успевает их обработать. В реальности такая ситуация может возникнуть в любой момент, поэтому крайне важно научиться ее предотвращать. Допущение об отсутствии ошибок в канале связи сохраняется. Линия остается симплексной.
Одно из решений — сконструировать целевое устройство так, чтобы его мощности хватало на обработку непрерывного потока последовательных фреймов (или же установить на канальном уровне достаточно низкую скорость передачи во избежание перегрузки получателя). У принимающей стороны должен быть буфер большого объема, а скорость обработки — не ниже скорости передачи данных. Кроме того, он должен быстро передавать фреймы сетевому уровню. Это наихудшее из возможных решений. Оно требует специального оборудования, а если линия загружена слабо, то ресурсы расходуются зря. Кроме того, такое решение всего лишь перекладывает проблему слишком быстрой передачи на чужие плечи: в данном случае ее приходится решать сетевому уровню.
Лучшее решение проблемы — обратная связь со стороны получателя. Передав пакет сетевому уровню, он посылает источнику небольшое служебное сообщение, разрешающее отправку следующего фрейма. Отправитель, отослав фрейм, должен ждать этого разрешения. Подобная задержка — простейший пример протокола с управлением потоком.
Протоколы, в которых отправитель посылает один фрейм, после чего ожидает подтверждения, называются протоколами с остановкой и ожиданием (stop-and-wait). На илл. 3.13 приведен пример такого симплексного протокола.
Хотя пересылка данных в этом примере осуществляется по симплексному принципу, по направлению от отправителя получателю, на практике фреймы идут и в обратную сторону. Следовательно, линия связи между двумя канальными уровнями должна поддерживать двунаправленную передачу. Однако данный протокол диктует жесткое чередование направлений пересылки: источник и получатель отправляют фреймы строго по очереди. Для такой реализации хватило бы полудуплексного физического канала.
Как и в протоколе 1, в начале цикла отправитель извлекает пакет с сетевого уровня, формирует из него фрейм и отправляет фрейм по линии связи. Отличие в том, что теперь он должен ждать получения фрейма с подтверждением, прежде чем запустить новую итерацию цикла и обратиться к сетевому уровню за следующим пакетом. В данной модели канальный уровень отправителя даже не просматривает входящий фрейм, поскольку он всегда означает только одно: подтверждение.
Единственное отличие между процедурами receiver2 и receiver1 состоит в том, что после передачи пакета сетевому уровню receiver2 посылает подтверждение обратно отправителю, после чего идет на следующую итерацию цикла. Поскольку для отправителя важно само прибытие ответного фрейма, а не его содержание, то получателю не нужно заполнять его специальной информацией.
Добавляем исправление ошибок: порядковые номера и протокол ARQ
Теперь рассмотрим реальную ситуацию: канал связи, в котором могут быть ошибки. Фреймы могут либо повреждаться, либо теряться. Однако мы будем считать, что если фрейм был изменен при передаче, то аппаратное обеспечение целевого устройства определит это, подсчитав контрольную сумму. Если фрейм поврежден таким образом, что контрольная сумма сходится (что очень маловероятно), то этот и любой другой протокол могут дать сбой, то есть отправить на сетевой уровень пакет с ошибками.
/* Протокол 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; /* скопировать его во фрейм s для передачи */
to_physical_layer(&s); /* отправка фрейма */
wait_for_event(&event); /* не продолжать, пока на это не будет получено разрешения */
}
}
void receiver2(void)
{
frame r, s; /* буферы для фреймов */
event_type event; /* frame_arrival является единственным возможным событием */
while (true) {
wait_for_event(&event); /* единственная возможность — прибытие фрейма (событие frame_arrival) */
from_physical_layer(&r); /* получить входящий фрейм */