Есть три способа определить, открыта ли розетка или нет, но ни один из них не является на 100% полным доказательством.
Первый - для попытки чтения в сокете следующим образом :
my $ret = recv($sockfd, $buff, 1, MSG_PEEK | MSG_NOWAIT);
Если сокет прошел упорядоченное отключение, то есть одноранговый узел, названный shutdown
для записи или вызываемый close
И пакет FIN
, прибыл, тогда этот вызов приведет к чтению длины 0, указывающему на закрытый сокет. Это также помогает в случае сбоя вашего однорангового приложения, поскольку ОС закроет соединение и отправит FIN
. Однако, если ваш одноранговый компьютер вышел из строя или ваше одноранговое приложение заблокировалось, это не поможет, поскольку каждый конец соединения поддерживает независимое состояние.
Второй способ обнаружить разорванное соединение - это проверить вашего партнера. Если вы отправили пакет 0 длины своему партнеру (который должен уметь обрабатывать), и приложение упало, тогда вы отправите второй пакет 0 длины, ваше приложение получит сигнал SIG_PIPE
, указывающий на сломанный канал .
Другим способом решения этой проблемы является использование пульса прикладного уровня, при котором одноранговые узлы периодически отправляют друг другу пакеты пульса, указывающие, что они живы и функционируют должным образом.
Последний вариант - использовать опцию сокета SO_KEEPALIVE
, хотя это ограниченное использование, поскольку он обнаружит сломанную розетку только после примерно 2 часов бездействия.
Если вы действительно должны знать достаточно быстро, когда соединение разрывается, то наиболее надежным вариантом, вероятно, будет пульс уровня приложения.