tcp — время Keepalive — не может быть меньше одной минуты в переполнении стека

Я реализую время активности активности в приложении C ++, которое записывает данные в порт TCP с помощью приведенного ниже кода. Это не показано, но я на самом деле проверяю действительный статус возврата, чтобы убедиться, что настройки параметров работают.

int option = 1;
int keepalive_intvl = 1;
int keepalive_count = 1;
int keepalive_idle = 1;

setsockopt(the_socket, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof (int) );
setsockopt(the_socket, SOL_TCP, TCP_KEEPINTVL, &keepalive_intvl, sizeof(int));
setsockopt(the_socket, SOL_TCP, TCP_KEEPCNT, &keepalive_count, sizeof(int));
setsockopt(the_socket, SOL_TCP, TCP_KEEPIDLE, &keepalive_idle, sizeof(int));

Мое приложение выполняет запись в порт TCP и пытается выполнить запись несколько раз в секунду.

// write null packet to determine if connection is still good
return ( send( GetDescriptor(),(char*)NULL, 0, 0 ) != -1 );

Всякий раз, когда я закрываю другое входное соединение, моему приложению требуется одна минута, чтобы сообщить о том, что соединение разорвано, на основании приведенного выше теста. Если у меня есть SIGPIPE функция-обработчик, для вызова которой также требуется одна минута.

Каждая документация, которую я видел, указывает, что параметры keepalive указаны в секундах, а не в минутах. Но я не могу обнаружить потерянное соединение ниже одной минуты.

Я также попытался изменить системные переменные, связанные с keepalive, которые обсуждались на tldp.org, но безрезультатно.

echo 1 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 1 > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo 1 > /proc/sys/net/ipv4/tcp_keepalive_probes

Управляется ли это поведение другим системным параметром? Действительно ли параметры keepalive находятся в минутах, что противоречит какой-либо документации? Есть ли определенная функция, которую я должен искать в коде, который может повлиять на этот параметр времени ожидания?

2

Решение

Ваша лучшая ставка — это поддержка уровня приложений; то есть отправлять сообщение об отсутствии операции (NOP) каждые X секунд и ожидать достаточно быстрого подтверждения NOP (NOP-ACK). Кроме того, если ваше удаленное соединение «изящно», то ваше send должен разблокировать почти сразу. Если это не изящно (например, произошел сбой сетевого элемента), то поддержание активности на уровне приложения обнаружит потерю в следующий раз, когда X + (ожидаемое время ответа) …

1

Другие решения

TCP_KEEPCNT (начиная с Linux 2.4)
Максимальное количество тестов keepalive, которые TCP должен отправить до разрыва соединения. Эта опция не должна использоваться в коде, предназначенном для переносимости.

Может быть, это может быть причиной. Вы можете реализовать свою собственную поддержку активности в вашем приложении, это должно быть довольно просто. Просто начните тыкать другой конец, если не поступает никаких данных о приложениях или «бьется сердце».

1

Я могу изменить общее время активности TCP_LINGER2 значение.

Всякий раз, когда я закрываю входной процесс TCP, я использую netstat -an чтобы получить следующие строки.

tcp        1      0 127.0.0.1:32962         127.0.0.1:7780          CLOSE_WAIT
tcp        0      0 127.0.0.1:7780          127.0.0.1:32962         FIN_WAIT2

Я могу это изменить FIN_WAIT2 Время двумя разными способами.

На уровне системы, в соответствии с этим ссылка на сайт, Я могу изменить его, изменив системный файл следующим образом:

% cat /proc/sys/net/ipv4/tcp_fin_timeout
60

[To change this to 3 seconds]
# echo "3" > /proc/sys/net/ipv4/tcp_fin_timeout

Мое выходное приложение TCP указывает, что соединение разорвано примерно за четыре секунды (я представляю 3 для времени ожидания, 1 для режима ожидания активности).

Я также могу изменить это на уровне отдельных сокетов в коде. В файле /usr/include/netinet/tcp.hЯ вижу следующее

#define TCP_LINGER2  8  /* Life time of orphaned FIN-WAIT-2 state */

Итак, добавив следующее в моем коде,

int wait_time = 3;
setsockopt(the_socket, SOL_TCP, TCP_LINGER2, &wait_time,sizeof(int));

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

Я согласен с другими ответами в том, что keepalive на уровне приложений — действительно правильный путь. И, как уже упоминалось Вот,

RFC 1122, раздел 4.2.3.6 указывает, что подтверждения для TCP
сообщения поддержки активности без данных не могут быть надежно переданы маршрутизаторами;
это может привести к разрыву действительных соединений. Кроме того, TCP / IP
стеки вообще не обязаны поддерживать keepalive (и многие
встроенных стеков нет), поэтому данное решение может не переводиться на другие
платформ.

Однако в не тестовой среде у меня нет доступа к входам TCP, в которых я могу реализовать другую сторону keepalive уровня приложения, поэтому keepalive TCP может быть моей единственной опцией.

1
По вопросам рекламы [email protected]