Мы удалили все объявления окна, за исключением сегмента 72, который мы обсудим ниже. slip всегда объявляет окно равное 4096, а vangogh объявляет окно равное 8192. Сегменты на этом рисунке пронумерованы как продолжение рисунка 21.2, где первый сегмент данных по соединению был с номером 1. Как и на рисунке 21.2, сегменты пронумерованы в соответствии с тем, как они отправлялись или принимались на хосте slip, где была запущена программа tcpdump. Мы также удалили несколько сегментов, которые не имели отношения к нашему обсуждению (44, 47 и 49, а также все ACK от vangogh).
Случилось так, что сегмент 45 либо потерялся, либо пришел поврежденным - мы не можем сказать этого определенно, основываясь на выводе команды. Все что мы можем увидеть на хосте slip это то, что было подтверждено все, за исключением байта 6657 (сегмент 58), за которым следовали следующие восемь ACK с тем же самым номером последовательности. Прием сегмента 62, третьего из дублированных ACK, вызвал повторную передачу данных, начиная с номера последовательности 6657 (сегмент 63). В действительности, реализации, происходящие от Berkeley, подсчитывают количество принятых дублированных ACK, и когда принимается третий, они подразумевают, что сегмент потерян, и повторно передают только один сегмент, начиная с этого номера последовательности. Подобное поведение является частью алгоритма быстрой повторной передачи (fast retransmit), который следует за алгоритмом быстрого восстановления данных (fast recovery algorithm), которые мы обсудим в разделе "Быстрая повторная передача и алгоритм быстрого восстановления" этой главы.
Обратите внимание на то, что после повторной передачи (сегмент 63) отправитель продолжает обычную передачу данных (сегменты 67, 69 и 71). TCP не ожидает того, что удаленный конец подтвердит повторную передачу.
Давайте посмотрим, что происходит на принимающем конце. Когда обычные данные приходят последовательно (сегмент 43), принимающий TCP передает 256 байт данных пользовательскому процессу. Однако следующий принятый сегмент (сегмент 46) не в порядке; стартовый номер последовательности данных (6913) не является следующим ожидаемым номером последовательности (6657). TCP сохраняет 256 байт данных и отвечает посредством ACK с самый большим номером последовательности, который был принят успешно, плюс один (6657). Следующие семь сегментов, принятых vangogh (48, 50, 52, 54, 55, 57 и 59), также не в порядке. Данные сохраняются принимающим TCP, и генерируются дублированные ACK.
Таким образом, для TCP не существует способа сообщить удаленному концу, что сегмент отсутствует. Помимо этого TCP не может подтвердить поврежденные данные. Все что может сделать vangogh в подобном случае - это продолжать посылать ACK с номером 6657.
Когда прибывают отсутствующие данные (сегмент 63), принимающий TCP имеет в своем буфере байты данных 6657-8960. Он передает эти 2304 байта пользовательскому процессу. Все 2304 байта подтверждены в сегменте 72. Также обратите внимание на то, что этот ACK объявляет окно равное 5888 (8192 - 2304), так как пользовательский процесс не имеет возможности прочитать 2304 байта, которые уже готовы для него.
Если мы рассмотрим более подробно вывод команды tcpdump для моментов времени 14 и 21 на рисунке 21.6, то увидим, что они были вызваны получением трех дублированных ACK, а это указывает на то, что пакет был потерян. Во всех этих случаях только один пакет был передан повторно.
Мы продолжим рассмотрение этого примера в разделе "Пример переполнения (продолжение)" этой главы, после того как рассмотрим более подробно алгоритм предотвращения переполнения.