Книга Компьютерные сети. 6-е изд. - Эндрю Таненбаум
Шрифт:
Интервал:
Закладка:
stop_timer(r.ack); /* остановить таймер */
from_network_layer(&buffer); /* получить следующий пакет у сетевого уровня */
inc(next_frame_to_send); /* инвертировать порядковый номер посылаемого фрейма */
}
}
s.info = buffer; /* подготовить фрейм для передачи */
s.seq = next_frame_to_send; /* вставить порядковый номер во фрейм */
s.ack = 1 – frame_expected; /* порядковый номер последнего полученного фрейма */
to_physical_layer(&s); /* передать фрейм */
start_timer(s.seq); /* запустить таймер ожидания подтверждения */
}
}
Илл. 3.16. Однобитный протокол раздвижного окна
В обычной ситуации только один канальный уровень может начинать передачу. Другими словами, лишь одна из программ должна содержать обращения к процедурам to_physical_layer и start_timer вне основного цикла. Отправитель получает первый пакет от своего сетевого уровня, создает из него фрейм и посылает его. Когда этот (или другой) фрейм приходит, получающий канальный уровень проверяет, не является ли он дубликатом, аналогично протоколу 3. Если это тот фрейм, который ожидался, он передается сетевому уровню и окно получателя сдвигается вверх.
Поле подтверждения содержит номер последнего полученного без ошибок фрейма. Если он совпадает с номером фрейма, который пытается передать отправитель, тот понимает, что этот фрейм успешно принят получателем и что можно пересылать следующий. В противном случае он продолжает попытки передачи того же фрейма. При каждом получении фрейма производится отправка фрейма в обратном направлении.
Теперь изучим протокол 4 и посмотрим, насколько он устойчив к нестандартным ситуациям. Представим, что устройство A пытается послать фрейм 0 устройству B, при этом B пытается отправить A фрейм 0. Предположим, что на A установлен слишком короткий период ожидания подтверждения. Соответственно, A посылает серию одинаковых фреймов со значениями полей seq = 0 и ack = 1.
Когда первый неповрежденный фрейм придет на устройство B, он будет принят и значение переменной frame_expected будет равно 1. Все последующие входящие фреймы будут проигнорированы, поскольку B теперь ожидает фрейм с порядковым номером 1, а не 0. Более того, поскольку у всех дубликатов значение поля ack = 1, а устройство B продолжает ожидать подтверждения для фрейма 0, оно не станет запрашивать новый пакет у своего сетевого уровня.
В ответ на каждый отвергнутый дубликат, присылаемый устройством A, B посылает фрейм, содержащий поля seq = 0 и ack = 0. Наконец, один из этих фреймов принимается A, в результате чего A переходит к передаче следующего пакета. Никакая комбинация потерянных фреймов или преждевременно истекших интервалов ожидания не может заставить этот протокол ни выдать сетевому уровню дубликат пакета, ни пропустить пакет, ни зависнуть. Протокол работает корректно.
Однако отношения между протоколами могут быть довольно непростыми. Если обе стороны одновременно вышлют друг другу начальный пакет, возникает запутанная ситуация, представленная на илл. 3.17. В левой части рисунка показан случай нормального функционирования протокола. Правая часть демонстрирует отклонение. Если B ожидает первый фрейм от A, прежде чем послать свой первый фрейм, то последовательность будет как в левой части рисунка (а). При этом принимается каждый фрейм.
Но если A и B одновременно начнут передачу, их первые фреймы пересекутся и канальные уровни попадут в ситуацию (б). В ситуации (а) с каждым фреймом приходит новый пакет и дубликатов нет. В случае (б) половина фреймов содержит дубликаты, несмотря на то что ошибок в канале связи не было. Причиной может стать преждевременный тайм-аут, даже если одна сторона явно начинает диалог первой. Получается, если время ожидания истечет слишком быстро, фрейм может быть послан три и более раза, приводя к ненужной трате ценных ресурсов.
Илл. 3.17. Два сценария для протокола 4. (а) Нормальная ситуация. (б) Нештатная ситуация. Обозначения в скобках: (seq, ack, номер пакета). Звездочка показывает, что сетевой уровень принял пакет
Протокол с возвратом к n
До сих пор мы по умолчанию подразумевали, что время, необходимое на передачу фрейма от отправителя к получателю и на обратную передачу подтверждения, пренебрежимо мало. Иногда это совершенно не так. Длительное время прохождения фреймов по сети может значительно снижать эффективность использования пропускной способности канала. В качестве примера рассмотрим 50-килобитный спутниковый канал. Время прохождения сигнала в оба конца равно 500 мс. Попытаемся использовать протокол 4 для пересылки фреймов размером 1000 бит через спутник. В момент времени t = 0 начинается отправка первого фрейма. При t = 20 мс фрейм полностью отправлен. Не раньше чем при t = 270 мс получатель принимает фрейм целиком и высылает подтверждение. Отправитель получает его в момент времени t = 520 мс (в самом лучшем случае — при нулевом времени ожидания на принимающей стороне и коротком фрейме подтверждения). Это означает, что отправляющее устройство заблокировано в течение 500/520, или 96 % времени. Другими словами, использовалось только 4 % доступной полосы пропускания. Очевидно, что сочетание большого времени прохождения сигнала, высокой пропускной способности и коротких фреймов совершенно неприемлемо с точки зрения эффективности.
Описанная выше проблема — следствие правила, которое обязывает отправителя дожидаться подтверждения, прежде чем посылать следующий фрейм. Смягчив это требование, можно значительно повысить эффективность. Нужно разрешить отправителю посылать не один фрейм, а несколько, например w, прежде чем остановиться и перейти в режим ожидания подтверждений. Если подобрать достаточно большое число w, то отправитель сможет безостановочно посылать фреймы, так как подтверждения для предыдущих фреймов будут приходить до того, как окно заполнится. Это предотвратит блокировку отправителя.
Чтобы найти подходящее значение w, необходимо понять, сколько фреймов «вмещается» в канал, в то время как они передаются от отправителя к получателю. Емкость определяется путем умножения полосы пропускания в битах в секунду на время пересылки в одну сторону. Это значение можно разделить на число битов во фрейме, чтобы выразить число фреймов. Назовем эту величину BD (bandwidth-delay product — полоса пропускания, умноженная на задержку). Следовательно, w должно соответствовать 2BD + 1. 2BD — это число фреймов, которое может находиться в пути (неподтвержденные фреймы), если отправитель передает фреймы непрерывно (с учетом времени на получение подтверждения). Единица прибавляется, так как фрейм подтверждения отправляется только после приема полного фрейма данных.
В качестве примера возьмем канал с полосой пропускания 50 Кбит/с, в котором на пересылку фрейма в одну сторону тратится 250 мс. Значение BD равно 12,5 Кбит/с или 12,5 фрейма, каждый из которых включает 1000 бит. 2BD + 1 равно 26 фреймам. Отправитель начинает, как и ранее, с передачи фрейма 0 и отправляет очередной фрейм каждые 20 мс. К тому моменту, когда он закончит отправку 26 фреймов (при t = 520 мс), как раз