На илл. 6.16 показан пример управления динамическим окном в дейтаграммной сети с 4-битными порядковыми номерами. Данные передаются в виде сегментов от хоста A к хосту B, а подтверждения и запросы на предоставление буферов идут в обратном направлении (также в виде сегментов). Вначале A запрашивает 8 буферов, но ему выделяется только 4. Затем он отправляет 3 сегмента; последний теряется. На шаге 6 A получает подтверждение получения переданных им сегментов 0 и 1, в результате чего он может освободить буферы и отправить еще 3 сегмента (2, 3 и 4). Хост A знает, что сегмент номер 2 он уже отправлял, поэтому думает, что может передать сегменты 3 и 4 (что он и делает). На этом шаге он блокируется, так как его счетчик буферов достиг нуля и ждет предоставления новых буферов. На шаге 9 наступает тайм-аут хоста А, так как он до сих пор не получил подтверждения для сегмента 2. Этот сегмент отсылается еще раз. В строке 10 хост B подтверждает получение всех сегментов, включая 4-й, но отказывается предоставлять буферы хосту A. Такая ситуация невозможна в протоколах с фиксированным размером окна, описанных в главе 3. Следующий сегмент, отправленный хостом B, разрешает хосту A передать еще один сегмент. Это происходит, когда у B появляется свободное буферное пространство, — скорее всего, потому, что пользователь службы принял больше данных.
Проблемы при такой схеме выделения буферов в дейтаграммных сетях могут возникнуть, если потеряется управляющий сегмент (а это действительно может произойти). Взгляните на строку 16. Хост B выделил хосту A дополнительные буферы, но сообщение об этом потерялось. Вот так неожиданность! Поскольку получение управляющих сегментов не подтверждается и они не отправляются повторно по тайм-ауту, хост A блокируется всерьез и надолго. Для предотвращения такой тупиковой ситуации каждый хост должен периодически отправлять управляющий сегмент с подтверждением и сведениями о состоянии буферов для каждого соединения. Это позволит в конце концов выбраться из тупика.
До сих пор мы предполагали, что единственное ограничение, накладываемое на скорость передачи данных, состоит в объеме свободного буферного пространства у получателя. Однако часто это не так. По мере колоссального снижения цен (некогда очень высоких) на микросхемы памяти и жесткие диски становится возможным оборудовать хосты таким количеством памяти, что проблема нехватки буферов возникает очень редко, даже если соединение охватывает крупные территории. Конечно, выбранный буфер должен быть достаточно большим; в случае TCP это требование не всегда выполнялось (Чжан и др.; Zhang et al., 2002).
Илл. 6.16. Динамическое выделение буферов. Стрелками показано направление передачи. Многоточие (…) означает потерянный сегмент
Если размер буферов перестанет ограничивать максимальный поток, возникнет другое узкое место: пропускная способность сети. Допустим, максимальная скорость обмена фреймами между соседними маршрутизаторами составляет x фреймов в секунду, а между двумя хостами имеется k непересекающихся путей. Сколько бы ни было буферов у обоих хостов, они не смогут пересылать друг другу больше чем kx сегментов в секунду. И если отправитель будет передавать быстрее, то сеть будет перегружена.
Требуется механизм, ограничивающий передачу данных со стороны отправителя, который основан не столько на емкости буферов получателя, сколько на пропускной способности сети. В 1975 году Белснес (Belsnes) предложил использовать для управления потоком данных схему раздвижного окна, в которой отправитель динамически приводит размер окна в соответствие с пропускной способностью сети.
Таким образом, раздвижное окно позволяет одновременно реализовать и управление потоком, и контроль перегрузки. Если сеть может обработать c сегментов в секунду, а время цикла (включая передачу, распространение, ожидание в очередях, обработку получателем и возврат подтверждения) равно r, тогда размер окна отправителя должен быть равен cr. При таком окне отправитель максимально использует канал. Любое снижение производительности сети приведет к его блокировке. Так как пропускная способность меняется с течением времени, размер окна должен настраиваться довольно часто, чтобы отслеживать изменения пропускной способности. Как будет показано ниже, в TCP используется похожая схема.
6.2.5. Мультиплексирование
Мультиплексирование (multiplexing), или объединение нескольких сеансов связи в одном соединении, виртуальном канале и одной физической линии, играет важную роль на нескольких уровнях сетевой архитектуры. На транспортном уровне такая потребность возникает в нескольких случаях. Например, если у хоста имеется только один сетевой адрес, он используется всеми соединениями транспортного уровня. Необходим способ, с помощью которого можно различать, какому процессу нужно передать входящий сегмент. Пример мультиплексирования показан на илл. 6.17 (а): четыре различных соединения транспортного уровня используют одно сетевое соединение (например, один IP-адрес) с удаленным хостом.