Это потому, что вы не использовали keepalive timeout.
На принимающей стороне опция сокета keepalive - лучшее решение для обнаружения разрыва соединения.
Но, если ваше приложение продолжит писать в сокет, есть над чем подумать.
Даже если вы уже установили опцию keepalive для сокета своего приложения, вы не можете вовремя обнаружить состояние разрыва соединения сокета, если ваше приложение продолжает писать в сокет.
Это из-за повторной передачи tcp стеком tcp ядра.
tcp_retries1 и tcp_retries2 являются параметрами ядра для настройки времени ожидания повторной передачи tcp.
Трудно предсказать точное время ожидания повторной передачи, потому что оно рассчитывается по механизму RTT.
Вы можете увидеть это вычисление в rfc793. (3.7. Передача данных)
https://www.rfc -editor.org / rfc / rfc793.txt
Каждая платформа имеет конфигурации ядра для повторной передачи tcp.
Linux : tcp_retries1, tcp_retries2 : (exist in /proc/sys/net/ipv4)
http://linux.die.net/man/7/tcp
HPUX : tcp_ip_notify_interval, tcp_ip_abort_interval
http://www.hpuxtips.es/?q=node/53
AIX : rto_low, rto_high, rto_length, rto_limit
http://www -903.ibm.com / кр / событие / загрузить / 200804_324_swma / socket.pdf
Вам следует установить более низкое значение для tcp_retries2 (по умолчанию 15), если вы хотите раннее обнаружение разорванного соединения, но это не точное время, как я уже сказал.
Кроме того, в настоящее время вы не можете установить эти значения только для одного сокета. Это глобальные параметры ядра.
Было несколько попыток применить опцию сокета повторной передачи tcp для одного сокета (http://patchwork.ozlabs.org/patch/55236/),, но я не думаю, что он был применен к основному ядру ядра. Я не могу найти определение этих опций в заголовочных файлах системы.
Для справки, вы можете отслеживать опцию keepalive через «netstat --timers», как показано ниже.
https://stackoverflow.com/questions/34914278
netstat -c --timer | grep "192.0.0.1:43245 192.0.68.1:49742"
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (1.92/0/0)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (0.71/0/0)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (9.46/0/1)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (8.30/0/1)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (7.14/0/1)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (5.98/0/1)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (4.82/0/1)
Кроме того, при возникновении тайм-аута keepalive вы можете встретить различные события возврата в зависимости от используемых вами платформ, поэтому вы не должны определять состояние разорванного соединения только событиями возврата.
Например, HP возвращает событие POLLERR, а AIX возвращает только событие POLLIN, когда происходит тайм-аут keepalive.
В это время вы встретите ошибку ETIMEDOUT в вызове recv ().
В последней версии ядра (начиная с 2.6.37), вы можете использовать опцию TCP_USER_TIMEOUT, которая будет работать хорошо. Эта опция может быть использована для одного сокета.