Подтвердить что ты не робот

Как правильно использовать SO_KEEPALIVE, чтобы обнаружить, что клиент с другого конца не работает?

поэтому я пытался изучить использование опции SO_KEEPALIVE в программировании сокетов на языке C. в среде Linux.

Я создал сокет сервера и использовал мой браузер для подключения к нему. Это было успешно, и я смог прочитать запрос GET, но я застрял в использовании SO_KEEPALIVE.

Я проверил эту ссылку [email protected], но я не смог найти ни одного примера, показывающего, как его использовать.

Как только я обнаруживаю клиентский запрос в функции accept(), я устанавливаю значение параметра SO_KEEPALIVE 1 в клиентском сокете. Теперь я не знаю, как проверить, закрыт ли клиент?, Как изменить временной интервал между отправленными пробками и т.д.

Я имею в виду, как я получу сигнал о том, что клиент не работает (без чтения или записи на клиенте... Я думал, что получаю сигнал, когда зонды не будут возвращены от клиента), как мне его запрограммировать установка опции SO_KEEPALIVE.

Также, если предположить, что пробники отправляются каждые 3 секунды, а клиент идет между ними, я не узнаю, что клиент выключен, и я могу получить SIGPIPE.

В любом случае важно знать, как использовать SO_KEEPALIVE в коде.

Спасибо за тонну заранее.

4b9b3361

Ответ 1

Чтобы изменить количество зондов или интервалов зонда, вы записываете значения в файловую систему /proc, например

 echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time
 echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl
 echo 20 > /proc/sys/net/ipv4/tcp_keepalive_probes

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

Вы не можете "проверить" статус сокета из пользовательского пространства с помощью keepalive. Вместо этого ядро ​​просто более агрессивно относится к тому, чтобы заставить удаленный конец распознавать пакеты и определять, не сошел ли сокет. Когда вы пытаетесь записать в сокет, вы получите SIGPIPE, если keepalive определил, что удаленный конец не работает.

Ответ 2

Вы получите тот же результат, если вы включите SO_KEEPALIVE, как если бы вы не включили SO_KEEPALIVE - обычно вы найдете готовый сокет и получите сообщение об ошибке при его чтении.

Вы можете установить тайм-аут keepalive для каждой розетки под Linux (это может быть специфичная для Linux функция). Я бы рекомендовал это, а не менял общесистемную настройку. Для получения дополнительной информации см. Справочную страницу tcp.

Наконец, если ваш клиент является веб-браузером, вполне вероятно, что он все равно быстро закроет сокет - большинство из них будут удерживать соединения keepalive (HTTP 1.1) в течение относительно короткого времени (30 с, 1 мин и т.д.).). Конечно, если клиентская машина исчезла или спустилась вниз (что SO_KEEPALIVE действительно полезно для обнаружения), тогда он не сможет активно закрыть сокет.

Ответ 3

Как уже обсуждалось, SO_KEEPALIVE делает ядро ​​более агрессивным, постоянно проверяя соединение, даже если вы ничего не делаете, но не меняете и не улучшаете способ доставки информации вам. Вы узнаете, когда попытаетесь что-то сделать (например, "написать" ), и вы сразу узнаете, так как ядро ​​теперь просто сообщает о статусе ранее установленного флага, вместо того, чтобы ждать нескольких секунд (или намного дольше в некоторых случаях) для сбоя сетевой активности. Точная та же логика кода, что и для обработки "другой стороны, ушла неожиданно", будет по-прежнему использоваться; какие изменения - время (а не метод).

Практически любая "практическая" программа сокетов в некотором роде обеспечивает неблокирующий доступ к сокетам во время фазы данных (возможно, с помощью select()/poll() или, возможно, с помощью fcntl()/O_NONBLOCK/EINPROGRESS & EWOULDBLOCK или если ваше ядро ​​поддерживает его, возможно, с MSG_DONTWAIT). Предполагая, что это уже сделано по другим причинам, тривиальным (иногда не требующим вообще никакого кода), чтобы дополнительно узнать об отключении соединения. Но если фаза данных еще не позволяет каким-то образом обеспечить неблокирующий доступ к сокетам, вы не узнаете об отключении соединения, пока в следующий раз вы не попытаетесь что-то сделать.

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