/* Протокол 1 («Утопия») обеспечивает только одностороннюю передачу данных — от отправителя к получателю. Предполагается, что в канале связи нет ошибок и получатель способен мгновенно обрабатывать входящие данные. Соответственно, отправитель в цикле передает данные на линию с максимально доступной для него скоростью.
typedef enum {frame_arrival} event_type;
#include “protocol.h”
void sender1(void)
{
frame s; /* буфер для исходящего фрейма */
packet buffer; /* буфер для исходящего пакета */
while (true) {
from_network_layer(&buffer); /* получить у сетевого уровня пакет для передачи */
s.info = buffer; /* скопировать его во фрейм s для передачи */
to_physical_layer(&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); /* передать данные сетевому уровню */
}
}
Илл. 3.12. Неограниченный симплексный протокол «Утопия»
Протокол «Утопия» абсолютно нереалистичен, так как он не способен ни управлять потоком данных, ни исправлять ошибки. Он напоминает службу без подтверждения и без установки соединения, которая надеется, что все эти проблемы решаются на более высоких уровнях. Однако даже такая служба обладает некоторыми способностями распознавать ошибки.
Добавляем управление потоком: протокол с остановкой и ожиданием
Усложним задачу: предположим, отправитель посылает данные слишком быстро и получатель не успевает их обработать. В реальности такая ситуация может возникнуть в любой момент, поэтому крайне важно научиться ее предотвращать. Допущение об отсутствии ошибок в канале связи сохраняется. Линия остается симплексной.
Одно из решений — сконструировать целевое устройство так, чтобы его мощности хватало на обработку непрерывного потока последовательных фреймов (или же установить на канальном уровне достаточно низкую скорость передачи во избежание перегрузки получателя). У принимающей стороны должен быть буфер большого объема, а скорость обработки — не ниже скорости передачи данных. Кроме того, он должен быстро передавать фреймы сетевому уровню. Это наихудшее из возможных решений. Оно требует специального оборудования, а если линия загружена слабо, то ресурсы расходуются зря. Кроме того, такое решение всего лишь перекладывает проблему слишком быстрой передачи на чужие плечи: в данном случае ее приходится решать сетевому уровню.
Лучшее решение проблемы — обратная связь со стороны получателя. Передав пакет сетевому уровню, он посылает источнику небольшое служебное сообщение, разрешающее отправку следующего фрейма. Отправитель, отослав фрейм, должен ждать этого разрешения. Подобная задержка — простейший пример протокола с управлением потоком.
Протоколы, в которых отправитель посылает один фрейм, после чего ожидает подтверждения, называются протоколами с остановкой и ожиданием (stop-and-wait). На илл. 3.13 приведен пример такого симплексного протокола.
Хотя пересылка данных в этом примере осуществляется по симплексному принципу, по направлению от отправителя получателю, на практике фреймы идут и в обратную сторону. Следовательно, линия связи между двумя канальными уровнями должна поддерживать двунаправленную передачу. Однако данный протокол диктует жесткое чередование направлений пересылки: источник и получатель отправляют фреймы строго по очереди. Для такой реализации хватило бы полудуплексного физического канала.