Когда TCP-соединение считается бездействующим?

У меня есть требование включить TCP keepalive на любых соединениях, и сейчас я борюсь с результатами нашего тестового примера. Я думаю, это потому, что я не совсем понимаю, когда отправляется первый тест активности активности. Я прочитал следующее в документации для tcp_keepalive_time в Linux:

интервал между последним отправленным пакетом данных (простые ACK не считаются данными) и первым тестом активности активности; после того, как соединение помечено как требующее поддержки, этот счетчик больше не используется

Некоторые другие источники утверждают, что это время, когда соединение простаивает, но они не определяют, что это значит. Я также посмотрел на Стивенса, чтобы найти более формальное определение этого, потому что мне интересно, что на самом деле означает "последний отправленный пакет данных" при рассмотрении повторных передач.

В моем тестовом примере у меня есть соединение, где данные отправляются только с сервера клиенту с довольно высокой скоростью. Чтобы проверить keepalive, мы отключили кабель от сетевой карты клиента. Теперь я вижу, что сетевой стек пытается отправить данные и переходит в состояние повторной передачи, но зонд проверки активности не отправляется. Правильно ли, что датчики активности не отправляются во время повторной передачи?

1 ответ

Решение

У меня есть соединение, где данные отправляются только с сервера клиенту с довольно высокой скоростью.

Тогда вы никогда не увидите keepalive. Keepalive отправляются, когда есть "молчание на проводе". RFC1122 имеет некоторые пояснения по поводу поддержки.

Механизм "keep-alive" периодически проверяет другой конец соединения, когда соединение в противном случае бездействует, даже когда нет данных для отправки

Вернуться к вашему вопросу:

Некоторые другие источники утверждают, что это время, когда соединение простаивает, но они не определяют, что это значит.

Это - то, как долго TCP будет ждать прежде, чем сунуть пира "хой! Все еще жив?"

$ cat /proc/sys/net/ipv4/tcp_keepalive_time
7200

Другими словами, вы использовали TCP-соединение, и это было здорово. Тем не менее, за последние 2 часа не было ничего, чтобы отправить. Разумно ли предположить, что связь все еще жива? Разумно ли предположить, что все промежуточные блоки в середине все еще имеют состояние вашего соединения? Мнения различаются, и сообщения активности не являются частью RFC793.

Спецификация TCP не включает механизм поддержания активности, который может: (1) привести к разрыву совершенно хороших соединений во время временных сбоев Интернета; (2) потреблять ненужную полосу пропускания ("если никто не использует соединение, кого это волнует, если оно все еще хорошо?")


Чтобы проверить keepalive, мы отключили кабель от сетевой карты клиента.

Это не тестирование keepalive. Это тестирование вашей стратегии повторной передачи TCP, т.е. сколько раз и как часто TCP будет пытаться донести ваше сообщение. На Linux-коробке это (скорее всего) заканчивается тестированием net.ipv4.tcp_retries2:

Как можно раз повторить попытку, прежде чем убить живое TCP-соединение. RFC 1122 говорит, что ограничение должно быть больше 100 сек. Это слишком маленькое число. Значение по умолчанию 15 соответствует 13-30 минутам в зависимости от RTO.

Но RFC5482 - опция времени ожидания пользователя TCP предоставляет больше способов повлиять на него.

Время ожидания пользователя TCP контролирует, как долго передаваемые данные могут оставаться неподтвержденными, прежде чем соединение принудительно закрывается.

Вернуться к вопросу:

Верно ли, что во время повторной передачи датчики поддержки остаются не отправленными?

Это имеет смысл: TCP уже пытается получить ответ от другого партнера, пустой keepalive был бы излишним.


Специфичные для Linux (2.4+) опции для влияния на keepalive

  • TCP_KEEPCNTМаксимальное количество тестов keepalive, которые TCP должен отправить до разрыва соединения.

  • TCP_KEEPIDLEВремя (в секундах), в течение которого соединение должно оставаться бездействующим, прежде чем TCP начнет отправлять тесты keepalive, если опция сокетаSO_KEEPALIVEбыл установлен на этом сокете

  • TCP_KEEPINTVLВремя (в секундах) между отдельными пробными сообщениями

Специфичная для Linux (2.6.37+) опция, влияющая на время ожидания пользователя TCP

TCP_USER_TIMEOUT Максимальное время в миллисекундах, в течение которого передаваемые данные могут оставаться неподтвержденными, прежде чем TCP принудительно закроет соединение.

Так, например, ваше приложение может использовать эту опцию, чтобы определить, как долго сохраняется соединение, когда нет соединения (аналогично вашему примеру отключения сетевого адаптера). Например, если у вас есть основания полагать, что клиент вернется (возможно, они закрыли крышку ноутбука "пятнистый беспроводной доступ"), вы можете указать время ожидания 12 часов, и когда они вернутся, соединение все равно будет функционировать.

Другие вопросы по тегам