3.8 Обработка сбойных ситуаций в транспортных протоколах. Виды сбойных ситуаций, способы их обработки. Время жизни блока данных. Таймеры. Особенности протокола TCP.
Развернутый ответ: Обработка сбойных ситуаций в транспортных протоколах
1. Введение
Транспортный уровень (OSI уровень 4) отвечает за сквозную (end-to-end) доставку данных между приложениями на разных хостах. В отличие от сетевого уровня (IP), который работает по принципу «best effort» (максимально возможное усилие) и допускает потери пакетов, транспортный уровень должен гарантировать надежность (в случае TCP) или предоставлять механизмы контроля целостности (в случае UDP).
Основная проблема заключается в том, что нижележащая сеть (каналы, маршрутизаторы) ненадежна. Пакеты могут:
- Теряться (перегрузка, битые биты, обрыв связи).
- Дублироваться (из-за повторных передач).
- Приходить не в том порядке (из-за разных маршрутов).
- Задерживаться на неопределенное время (jitter).
Для борьбы с этим в транспортных протоколах реализованы сложные механизмы обработки сбойных ситуаций.
2. Виды сбойных ситуаций
Сбойные ситуации можно классифицировать по характеру нарушения:
Потеря сегмента (Data Loss):
- Перегрузка маршрутизатора: Буфер переполнен, и пакет отбрасывается (Drop).
- Битовые ошибки: Ошибка в контрольной сумме (Checksum) приводит к отбрасыванию пакета на приемной стороне.
- Обрыв канала: Физический разрыв соединения или уход маршрутизатора из сети.
Нарушение порядка (Out-of-Order):
- Пакеты, отправленные последовательно (1, 2, 3), приходят вразнобой (1, 3, 2), так как IP-маршрутизация динамична и пакеты могут идти разными путями.
Дублирование (Duplication):
- Возникает, когда отправитель не получил подтверждение (ACK) вовремя и повторно отправил сегмент, а первый сегмент на самом деле дошел, просто ACK задержался. Получатель получает две копии одного и того же блока данных.
Задержка (Delay / Reordering):
- Пакет «застрял» в буфере маршрутизатора на долгое время. Он приходит с большим опозданием, когда таймер отправителя уже истек, и данные были отправлены заново.
«Мертвое» соединение (Silent Failure):
- Один из участников обмена (или промежуточный узел) перезагружается (“краш”). Оставшаяся сторона не получает никаких явных уведомлений о разрыве и продолжает ждать данные (ситуация Half-Open или Zombie Connection).
3. Способы обработки сбойных ситуаций
Для борьбы с перечисленными проблемами используются несколько базовых стратегий:
- Нумерация последовательности (Sequence Numbers): Каждому байту или блоку данных присваивается уникальный номер. Это позволяет приемнику:
- Собрать данные в правильном порядке (Reordering).
- Обнаружить пропущенные блоки (по разрыву в номерах).
- Отбросить дубликаты (если номер уже был принят).
- Контрольные суммы (Checksums): Вычисление хэша от данных. Если хэш на приеме не совпадает с переданным, пакет уничтожается, и отправитель должен его повторить.
- Подтверждения (Acknowledgment - ACK): Приемник явно отправляет сообщение о получении данных. Отсутствие ACK является для отправителя сигналом о сбое.
- Повторная передача (Retransmission): Если отправитель не получил ACK за отведенное время, он отправляет те же данные повторно.
- Механизмы «скользящего окна»: Ограничивают количество данных, которые можно отправить без подтверждения, что позволяет контролировать перегрузку и управлять потоком.
4. Время жизни блока данных (Time To Live – TTL / Lifetime)
Это критически важный параметр для предотвращения бесконечного блуждания дубликатов в сети.
- На сетевом уровне (IP TTL): Это поле в заголовке IP, уменьшаемое на 1 каждым маршрутизатором. При достижении 0 пакет уничтожается. Это защита от петель маршрутизации.
- На транспортном уровне (MSL - Maximum Segment Lifetime): Это максимальное время, которое сегмент может существовать в сети. Оно определяет, как долго нужно ждать, прежде чем можно будет безопасно переиспользовать номера последовательностей.
- В TCP значение MSL обычно составляет 2 минуты (хотя часто в реализациях устанавливают 30–60 сек).
- Смысл: Если мы отправили данные и получили ACK, старые дубликаты этих данных должны гарантированно исчезнуть из сети до того, как мы начнем использовать их порядковые номера для новых данных. Время жизни напрямую связано со временем ожидания в состоянии
TIME_WAITу TCP.
5. Таймеры (Timers)
Таймеры — это главный инструмент для работы с неопределенностью времени доставки. Транспортные протоколы используют несколько типов таймеров:
Таймер повторной передачи (Retransmission Timer):
- Запускается при отправке сегмента.
- Если по его истечении ACK не получен, сегмент отправляется снова.
- Ключевая сложность: Выбор значения тайм-аута (RTO — Retransmission Timeout). Если поставить мало — будут ложные срабатывания и дубли. Если много — падает производительность.
- Алгоритм: Используется адаптивный расчет на основе RTT (Round Trip Time — время оборота). Рассчитывается средневзвешенное значение (SRTT) и вариация отклонений (RTTVAR):
RTO = SRTT + 4 * RTTVAR.
Таймер подтверждения (ACK Timer - Delayed ACK):
- Используется получателем. Он не отправляет ACK мгновенно на каждый пакет, а выжидает небольшое время (обычно до 200 мс), чтобы попытаться «прицепить» ACK к встречным данным (piggybacking) или подтвердить сразу несколько сегментов одним ACK.
Таймер сохранения (Persist Timer):
- Связан с управлением потоком (окно приема). Если отправитель получил от получателя сообщение с нулевым размером окна (
Window = 0), он останавливает отправку. Чтобы не ждать вечно, запускается Persist Timer. По его истечению отправитель шлет маленький зондирующий пакет (Probe), чтобы узнать, не освободилось ли окно у получателя.
- Связан с управлением потоком (окно приема). Если отправитель получил от получателя сообщение с нулевым размером окна (
Таймер контроля соединения (Keepalive Timer):
- Используется для проверки, жив ли партнер (приложение или хост) на другой стороне, при длительном простое.
- Если в течение заданного времени (например, 2 часа по умолчанию в Linux) нет обмена данными, отправляется пустой Keepalive-пакет. Если ответа нет несколько раз (и таймеры повторной передачи срабатывают), соединение разрывается.
6. Особенности протокола TCP в обработке сбоев
Протокол TCP является самым сложным транспортным протоколом с точки зрения надежности. Его ключевые особенности:
Трехэтапное установление соединения (Three-way Handshake):
- Перед отправкой данных стороны обмениваются SYN-пакетами, согласовывая начальные номера последовательностей (ISN). Это защищает от наложения “старых” сегментов от предыдущего соединения.
- Если SYN потерян, таймер повторной передачи на стороне клиента перезапускает попытку соединения.
Выборочное подтверждение (SACK - Selective Acknowledgment):
- Базовый TCP подтверждает только последний полученный непрерывный байт (Cumulative ACK). При потере одного пакета в середине окна, отправитель вынужден пересылать все пакеты начиная с потерянного (алгоритм Гоббса).
- SACK позволяет приемнику сообщить отправителю точный список блоков данных, которые он получил. Отправитель пересылает только реально потерянные данные, что значительно повышает эффективность при сбоях.
Управление перегрузкой (Congestion Control):
- Сбой (потеря пакета) в TCP рассматривается не только как проблема связи, но и как индикатор перегрузки сети.
- При срабатывании таймера повторной передачи или получении трех дублирующих ACK (указывающих на потерю), TCP включает механизмы уменьшения скорости отправки:
- Медленный старт (Slow Start) и Избегание перегрузок (Congestion Avoidance): Снижает размер окна перегрузки (
cwnd), чтобы разгрузить сеть.
- Медленный старт (Slow Start) и Избегание перегрузок (Congestion Avoidance): Снижает размер окна перегрузки (
- Алгоритм Reno и CUBIC (современный стандарт в Linux): При потере (таймаут) окно обнуляется, при трех дублированных ACK (слабая потеря) окно уменьшается наполовину.
Алгоритм Нейгла (Nagle’s Algorithm) и Алгоритм Кларка:
- Хотя это больше оптимизация, они влияют на сбои при работе с интерактивными приложениями. Алгоритм Нейгла буферизирует мелкие пакеты (телеграфный режим), отправляя их пачками, что предотвращает переполнение сети большим количеством мелких сегментов (т.н. синдром глупого окна - Silly Window Syndrome).
Закрытие соединения (Four-way Handshake и TIME_WAIT):
- При разрыве соединения TCP использует таймер для состояния
TIME_WAIT(длительностью 2 * MSL). - Особенность: Это делается для того, чтобы гарантировать, что все дубликаты последнего ACK и все старые пакеты исчезли из сети, прежде чем порт будет использован заново. Если бы не было TIME_WAIT, новый сеанс мог бы получить старые сегменты от завершенного сеанса.
- При разрыве соединения TCP использует таймер для состояния
7. Итоговая схема обработки потери (на примере TCP)
- Отправитель посылает сегмент с номером
Nи запускает Retransmission Timer. - Сценарий А (Успех): Получатель получает сегмент, проверяет Checksum, отправляет ACK
N+1. Отправитель получает ACK, сбрасывает таймер, сдвигает окно. - Сценарий Б (Потеря данных/ACK): Таймер истекает.
- Отправитель повторно отправляет сегмент
N. - Включается экспоненциальная пауза (Exponential Backoff): тайм-аут удваивается (чтобы не усугублять перегрузку).
- Отправитель повторно отправляет сегмент
- Сценарий В (Дубль): Получатель уже получил сегмент
N(но ACK потерялся) и при получении дубля просто отбрасывает его, но повторно отправляет ACK. - Если сбой продолжается, таймеры срабатывают несколько раз (обычно 5–15 попыток в зависимости от ОС), после чего соединение разрывается, и приложению возвращается ошибка (ETIMEDOUT).