Просматривая соединение с использованием tcpdump и отладочной опции сокетов (которую мы описали в разделе "Пример RTT"), мы можем увидеть значения cwnd и ssthresh при передаче каждого сегмента. Если максимальный размер сегмента (MSS) равен 256 байт, исходные значения cwnd и ssthresh будут равны 256 и 65535 соответственно. Каждый раз, когда принимается ACK, cwnd увеличивается на значение MSS и принимает значения 512, 768, 1024, 1280 и так далее. Предположим, что переполнения не происходит, поэтому окно переполнения достигнет значения окна, объявленного получателем, а это, в свою очередь, будет означать, что объявленное окно ограничивает поток данных.
Однако нам интересно посмотреть, что произойдет в случае возникновения переполнения. Рассмотрим тот же пример из раздела "Пример RTT". В этом примере переполнение появлялось четыре раза. Был тайм-аут при передаче исходного SYN, который предназначался для установления соединения (рисунок 21.5), после чего, в процессе передачи данных, было потеряно три пакета (рисунок 21.6).
На рисунке 21.9 показаны значения двух переменных cwnd и ssthresh, когда осуществлялась повторная передача исходного SYN, за которым следовало семь первых сегментов данных. (Мы показали обмен исходными сегментами данных и их ACK на рисунке 21.2.) Переданные байты данных показаны в формате вывода команды tcpdump: 1:257(256), что означает байты с 1 по 256.
Когда возникает тайм-аут при передаче SYN, ssthresh устанавливается в свое минимальное значение (512 байт, что равно, в этом примере, двум сегментам). cwnd устанавливается в один сегмент (256 байт), чтобы войти в фазу медленного старта.
Когда получены SYN и ACK, с этими переменными ничего не происходит, так как новые данные не были подтверждены.
Когда прибывает ACK 257, мы все еще находимся в режиме медленного старта, так как cwnd меньше либо равно ssthresh, поэтому cwnd увеличивается на 256. То же самое происходит, когда прибывает ACK 513.
Когда прибывает ACK 769, мы больше не находимся в режиме медленного старта, однако переходим в режим предотвращения переполнения. Новое значение cwnd рассчитывается следующим образом
cwnd ¬ cwnd + (разм.сегмента x разм.сегмента)/cwnd + разм.сегмента/8
Это больше на 1/cwnd, чем то, что мы показали ранее, принимая во внимание то, что cwnd рассчитывается в действительности в байтах, а не в сегментах. Для этого примера мы рассчитаем
cwnd ¬ 768 + (256 x 256)/768 + 256/8
Номер сегмента (рисунок 21.2) | Действие
|
Переменная | |||
Отправлено | Получено | Комментарий | cwnd | ssthresh | |
инициализация | 256 | 65535 | |||
SYN | |||||
SYN |
тайм-аут
повторная передача |
256 | 512 | ||
SYN, ACK | |||||
ACK | |||||
1 | 1:257(256) | ||||
2 | ACK 257 | медленный старт | 512 | 512 | |
3 | 257:513(256) | ||||
4 | 513:769(256) | ||||
5 | ACK 513 | медленный старт | 768 | 512 | |
6 | 769:1025(256) | ||||
7 | 1025:1281(256) | ||||
8 | ACK 769 | предотвращение переполнения | 885 | 512 | |
9 | 1281:1537(256) | ||||
10 | ACK 1025 | предотвращение переполнения | 991 | 512 | |
11 | 1537:1793(256) | ||||
12 | ACK 1281 | предотвращение переполнения | 1089 | 512 |