Компьютерные сети. 6-е изд. - Эндрю Таненбаум
Шрифт:
Интервал:
Закладка:
Выбор компромиссного решения между буферизацией на сторонах отправителя и получателя зависит от типа трафика. В случае неинтенсивного и нестабильного трафика, например, когда пользователь производит клавиатурный ввод на удаленном компьютере, лучше не выделять никаких буферов, а получать их динамически на обоих концах, полагаясь на буферизацию со стороны отправителя (на случай, если сегменты будут случайно удалены). С другой стороны, в случае передачи файла будет лучше, если получатель выделит целое окно буферов, чтобы данные могли передаваться с максимальной скоростью. Такую стратегию использует TCP.
Тем не менее открытым остается вопрос об организации набора буферов. Когда большинство сегментов примерно одинакового размера, логично организовать буферы в виде массива буферов равной величины, каждый из которых может вместить один сегмент (илл. 6.15 (а)). Но если сегменты сильно отличаются по размеру, от коротких запросов на загрузку веб-страниц до крупных пакетов при одноранговой передаче файлов, массив из буферов фиксированного размера окажется неудобным. Если буфер будет равен наибольшему возможному сегменту, то при хранении небольших сегментов память будет расходоваться неэффективно. Если же он будет меньше, тогда для хранения большого сегмента потребуется несколько буферов с сопутствующими сложностями.
Илл. 6.15. Организация набора буферов. (а) Цепочка буферов фиксированного размера. (б) Цепочка буферов переменного размера. (в) Один большой циклический буфер для одного соединения
Другой способ решения проблемы состоит в использовании буферов переменного размера (илл. 6.15 (б)). Преимущество этого метода заключается в оптимальном использовании памяти, но платой за это является более сложное управление буферами. Третий вариант состоит в выделении соединению единого большого циклического буфера (илл. 6.15 (в)). Эта простая и изящная схема работает независимо от размера сегментов, однако она эффективно использует память, только если все соединения сильно нагружены.
При открытии и закрытии соединений и при изменении формы трафика отправитель и получатель должны динамически изменять выделенные буферы. Следовательно, транспортный протокол должен позволять отправителю отправлять запросы на выделение буфера на другой стороне. Буферы могут выделяться для каждого соединения или коллективно на все соединения между двумя хостами. В качестве альтернативы запросам получатель, зная состояние своих буферов, но не зная, какой трафик ему будет предложен, может сообщить отправителю, что он зарезервировал для него Х буферов. При увеличении числа открытых соединений может потребоваться уменьшить количество или размеры выделенных буферов. Протокол должен предоставлять такую возможность.
В отличие от протокола раздвижного окна, описанного в главе 3, для реализации динамического выделения буферов следует отделить буферизацию от подтверждений. Динамическое выделение буферов на деле означает использование окна переменного размера. Сначала отправитель запрашивает определенное число буферов согласно своим потребностям. Получатель выделяет столько, сколько может. При отправлении каждого сегмента отправитель должен уменьшать число буферов на единицу, а когда оно достигнет нуля, он должен остановиться. Получатель отправляет обратно на попутных сегментах отдельно подтверждения и сведения об имеющихся у него свободных буферах. Эта схема используется в TCP; при этом информация о буферах хранится в поле заголовка Window size (Размер окна).
На илл. 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) предложил использовать для управления потоком данных схему раздвижного окна, в которой отправитель динамически приводит размер окна в соответствие с пропускной способностью сети.