На этом занятии вы углубитесь в механизмы TCP: как устанавливается и разрывается соединение (трёхкратное рукопожатие и завершение), как работает скользящее окно для эффективной доставки без ожидания подтверждения каждого сегмента, а также управление потоком (чтобы не затопить медленного получателя) и управление перегрузкой (чтобы не перегрузить сеть).
В практике вы разберёте в Wireshark установку и разрыв TCP-соединения, передачу данных и поля заголовка, связанные с окном.
Передача данных по протоколу TCP состоит из трёх этапов. Сначала необходимо установить соединение между отправителем и получателем. Затем по установленному соединению передаются данные. После завершения обмена соединение корректно разрывается.
В отличие от UDP, где данные можно отправить сразу, в TCP перед первой порцией данных всегда идёт обмен служебными сегментами для установки соединения, а после передачи - для разрыва. Это создаёт дополнительные накладные расходы, но позволяет реализовать надёжность и согласование параметров.
Установка соединения в TCP нужна по нескольким причинам. Во-первых, стороны убеждаются, что отправитель и получатель готовы передавать и принимать данные. Во-вторых, происходит синхронизация нумерации потока байт: стороны договариваются о начальных номерах (ISN), с которых будут нумероваться байты в каждом направлении. В-третьих, можно согласовать дополнительные параметры протокола (например, максимальный размер сегмента MSS, масштаб окна, выборочные подтверждения SACK).
Установка соединения выполняется процедурой, которая называется трёхкратное рукопожатие (three-way handshake). На первом шаге сторона, инициирующая соединение (клиент), отправляет сегмент, в заголовке которого установлен флаг SYN (synchronization). В этом же сегменте указывается начальный порядковый номер (ISN) - номер, с которого отправитель будет нумеровать байты своих данных в этом соединении.
Например, отправитель может выбрать ISN 7537. Этот номер не обязан быть нулём: он выбирается для защиты от смешивания сегментов старых и новых «инкарнаций» соединения при сбоях и перезагрузках.
Получатель (сервер) в ответ отправляет сегмент, в котором установлены два флага: SYN и ACK. Флаг ACK означает, что поле «номер подтверждения» значимо: получатель подтверждает получение сегмента SYN и указывает номер следующего ожидаемого байта (например, 7538). Одновременно получатель устанавливает флаг SYN и сообщает свой начальный порядковый номер для данных в обратную сторону (например, 36829). Таким образом, за один сегмент получатель и подтверждает приход запроса, и синхронизирует свою нумерацию.
Инициатор соединения отправляет третий сегмент с установленным флагом ACK. В нём указывается номер подтверждения - следующий ожидаемый байт от получателя (36830), а данные в этом сегменте начинаются с номера 7538. После этого оба направления синхронизированы: отправитель нумерует свои байты с 7537, получатель - с 36829. Соединение считается установленным, и можно передавать данные.
Почему нельзя всегда нумеровать байты с нуля? Из-за сбоев сети возможны ситуации с несколькими «инкарнациями» одного и того же логического соединения. Например, отправитель установил соединение, начал передавать данные, затем произошла перезагрузка приложения. Отправитель заново устанавливает соединение и снова передаёт данные. Если нумеровать с нуля, старые задержавшиеся в сети сегменты могут прийти после установки нового соединения, и получатель не сможет однозначно определить, к какой инкарнации они относятся.
Синхронизация при установке соединения задаёт начальные номера, которые со временем увеличиваются. Так обеспечивается защита от смешивания сегментов старых и новых инкарнаций.
Соединение TCP дуплексное: данные могут идти в обе стороны. Поэтому разрыв выполняется с двух сторон. Чтобы разорвать свою половину соединения, сторона отправляет сегмент с установленным флагом FIN (finish). Вторая сторона подтверждает получение запроса на разрыв (ACK). После этого направление «от отправителя FIN к получателю» закрыто - данные в эту сторону передавать нельзя. Но обратное направление ещё открыто.
Когда вторая сторона тоже хочет завершить передачу, она отправляет свой сегмент с FIN и получает ACK. Только после этого соединение считается полностью разорванным.
Для быстрого разрыва соединения без ожидания подтверждений используется сегмент с флагом RST (reset). В этом случае соединение разрывается сразу в обе стороны. RST обычно применяют при ошибках или когда одна из сторон не хочет принимать соединение. В нормальном сценарии закрытия приложения предпочтителен корректный разрыв по FIN.
В сетях используются два основных подхода к подтверждению доставки. Остановка и ожидание (stop-and-wait): отправитель передаёт одну порцию данных, останавливается и ждёт подтверждения; получив ACK, передаёт следующую порцию. Такой метод часто применяется на канальном уровне (например, в Wi-Fi).
В TCP используется другой подход - скользящее окно: отправитель может отправить несколько сегментов подряд, не дожидаясь подтверждения каждого. Получатель может подтвердить сразу несколько полученных сегментов одним кумулятивным подтверждением. Это значительно повышает эффективность использования канала в составных сетях с ненулевой задержкой.
При времени оборота (RTT) 10 мс и передаче по одному сегменту за раз за секунду можно отправить только около 100 сегментов. При типичном размере полезных данных в сегменте порядка 1460 байт это даёт примерно 143 Кбит/с - для современных гигабитных каналов крайне мало. Поэтому в TCP выгодно отправлять в сеть несколько сегментов подряд, не дожидаясь ACK на каждый - для этого и служит механизм скользящего окна.
Окно в контексте TCP - это данные (байты), которые уже отправлены в сеть, но получение которых ещё не подтверждено. Размер окна - это количество байт, которые разрешено передать в сеть без получения подтверждения. Сегменты, получение которых уже подтверждено, считаются «слева» от окна; ещё не отправленные - «справа». Окно «скользит» вперёд по потоку байт по мере прихода подтверждений: после ACK граница сдвигается, и можно отправлять новые данные.
В TCP по умолчанию используется кумулятивное подтверждение. В поле «номер подтверждения» указывается номер следующего ожидаемого байта. Это означает: «все байты до этого номера (не включая его) получены». Таким образом, один ACK подтверждает доставку всех предыдущих байт. Это удобно и экономит трафик. Кумулятивное подтверждение хорошо подходит для окон небольшого размера.
При большом размере окна может быть потерян один сегмент в середине потока. При только кумулятивном подтверждении отправитель вынужден повторно передавать все данные начиная с потерянного сегмента. Выборочное подтверждение (SACK) позволяет явно указать диапазоны уже полученных блоков данных. Тогда отправитель повторяет только реально потерянный фрагмент. SACK не используется по умолчанию - стороны должны согласовать его при установке соединения (опция в handshake).
Управление потоком (flow control) в TCP - это предотвращение затопления медленного получателя быстрым отправителем. Устройства в сети имеют разную производительность и разный размер буферов. Если отправитель (например, мощный сервер) будет слать данные слишком быстро, буфер на стороне получателя (например, смартфона) переполнится, лишние сегменты будут отброшены, и их придётся передавать заново. Управление потоком решает эту проблему.
Данные, приходящие по TCP, попадают в буфер операционной системы, откуда их читает приложение. Если приложение читает медленно или занято, буфер заполняется. В заголовке TCP получатель передаёт в каждом сегменте поле Window (размер окна) - сколько байт он готов принять. По сути, это объём свободного места в буфере. Отправитель не должен отправлять больше данных, чем указано в размере окна, иначе они могут быть отброшены.
Если буфер получателя заполнен, он может отправить подтверждение с размером окна 0. Это значит: «пока не готов принимать данные». Отправитель останавливает передачу и ждёт. Когда приложение прочитает данные из буфера, получатель отправит новое подтверждение с ненулевым размером окна. Если такое сообщение потеряется, отправитель может периодически отправлять небольшой сегмент-зонд (Zero Window Probe), чтобы получить актуальный размер окна.
Проблема перегрузки связана уже не с получателем, а с сетью. Если много отправителей одновременно передают много данных, маршрутизаторы и каналы не справляются - пакеты отбрасываются, отправители повторяют передачу, нагрузка растёт. В 1986 году в интернете произошёл коллапс перегрузки: каналы были забиты, но полезная скорость упала на порядки. После этого в TCP ввели механизмы управления перегрузкой (congestion control), чтобы размер отправляемых данных зависел от загрузки сети.
В TCP фактически используются два ограничения на объём неподтверждённых данных. Окно управления потоком задаётся получателем (поле Window в заголовке) - сколько байт он может принять. Окно перегрузки вычисляется отправителем на основе сигналов о загрузке сети (потери, задержки, явные уведомления ECN). Итоговый размер окна, которым руководствуется отправитель, - минимум из этих двух значений.
Один из базовых алгоритмов управления перегрузкой - AIMD (Additive Increase, Multiplicative Decrease). При отсутствии признаков перегрузки размер окна перегрузки понемногу увеличивается (например, на размер одного сегмента за каждое подтверждение). При появлении перегрузки (например, потеря сегмента) окно уменьшается в несколько раз (часто вдвое). Так протокол «нащупывает» подходящую скорость: осторожно наращивает и резко снижает при перегрузке. График размера окна во времени напоминает пилу.
Чистый AIMD на быстрых каналах приводит к медленному росту окна. Поэтому в TCP дополнительно используется медленный старт (slow start): в начале передачи окно перегрузки небольшое (например, 2-4 сегмента), а при получении каждого ACK окно увеличивается (например, удваивается), пока не достигнет порога. После этого применяется более плавное аддитивное увеличение. При сигнале перегрузки окно снова снижается. Детали описаны в RFC 5681.
Перегрузку можно определить по нескольким признакам. Самый надёжный - потеря сегмента (нет подтверждения, сработал таймаут или пришли дубликаты ACK). Часто потеря в современных сетях связана именно с перегрузкой. Другой признак - задержка: подтверждения приходят заметно позже. Третий - явное уведомление о перегрузке (ECN) от маршрутизаторов, если в сети поддерживается механизм ECN. На основе этих сигналов отправитель уменьшает окно перегрузки.
Установка соединения TCP - трёхкратное рукопожатие (SYN, SYN+ACK, ACK); разрыв - по FIN с каждой стороны или RST для сброса. Скользящее окно позволяет отправлять несколько сегментов без ожидания ACK; подтверждение может быть кумулятивным или выборочным (SACK). Управление потоком - через поле Window в заголовке (буфер получателя); управление перегрузкой - через окно перегрузки на стороне отправителя (AIMD, медленный старт). Итоговое окно - минимум из окна потока и окна перегрузки.
Далее - интерактивные задания, тест допуска и практика в Wireshark.
Расставьте этапы установки соединения TCP в правильном порядке (перетащите блоки).
Выберите верные утверждения.
Какой флаг TCP используется для корректного разрыва соединения (каждая сторона закрывает свою половину)?
Что делают при перегрузке в алгоритме AIMD?
Для доступа к практике нужно набрать не менее 80% - минимум 7 правильных ответов из 8.
1. Установка соединения TCP называется:
2. В первом сегменте установки соединения установлен флаг:
3. Для быстрого разрыва соединения без ожидания подтверждения используется флаг:
4. Скользящее окно в TCP нужно для:
5. Поле Window в заголовке TCP (управление потоком) задаётся:
6. Окно перегрузки в TCP определяет:
7. Алгоритм AIMD - это:
8. Итоговый размер окна, которым руководствуется отправитель TCP, равен:
Вы выполните пошаговые действия за компьютером: откроете сайт по HTTP (например, networks.ru или другой без шифрования), захватите трафик в Wireshark, примените фильтр по IP сайта. Затем разберёте установку соединения (три сегмента: SYN, SYN+ACK, ACK), передачу данных (поток байт, флаг PSH), разрыв соединения (FIN, ACK с обеих сторон). Файл для сдачи не требуется - проверка по результату на экране и по контрольным вопросам.
ip.addr == 93.184.216.34 для example.com или адрес вашего сайта). Так вы увидите только трафик между вашим компьютером и выбранным хостом. Убедитесь, что в списке есть TCP-пакеты.Ответьте себе (устно или в тетради):
Если вы уверенно находите в Wireshark этапы установки, передачи и разрыва - вы закрепили тему занятия.