Как я могу проверить состояние сокета TCP в Perl? - PullRequest
3 голосов
/ 24 марта 2010

У меня есть сокет TCP, который читает данные. Когда при чтении данных возникает ошибка, я возвращаю значение undef (NULL). Ошибки могут быть вызваны плохо отформатированными сообщениями или сломанными сокетами. Может кто-нибудь сказать мне, есть ли конкретная функция, которая возвращает состояние сокета?

Ответы [ 2 ]

7 голосов
/ 24 марта 2010

Есть три способа определить, открыта ли розетка или нет, но ни один из них не является на 100% полным доказательством.

Первый - для попытки чтения в сокете следующим образом :

my $ret = recv($sockfd, $buff, 1, MSG_PEEK | MSG_NOWAIT);

Если сокет прошел упорядоченное отключение, то есть одноранговый узел, названный shutdown для записи или вызываемый close И пакет FIN, прибыл, тогда этот вызов приведет к чтению длины 0, указывающему на закрытый сокет. Это также помогает в случае сбоя вашего однорангового приложения, поскольку ОС закроет соединение и отправит FIN. Однако, если ваш одноранговый компьютер вышел из строя или ваше одноранговое приложение заблокировалось, это не поможет, поскольку каждый конец соединения поддерживает независимое состояние.

Второй способ обнаружить разорванное соединение - это проверить вашего партнера. Если вы отправили пакет 0 длины своему партнеру (который должен уметь обрабатывать), и приложение упало, тогда вы отправите второй пакет 0 длины, ваше приложение получит сигнал SIG_PIPE , указывающий на сломанный канал .

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

Последний вариант - использовать опцию сокета SO_KEEPALIVE, хотя это ограниченное использование, поскольку он обнаружит сломанную розетку только после примерно 2 часов бездействия.

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

5 голосов
/ 24 марта 2010

doh !, ответ был очевиден в ретроспективе, используйте подключенный вызов.

$socket = IO::Socket::INET(localhost, 1000);
die "no connection" unless $socket -> connected();
$socket -> send("your face here for $20");
die "socket is dead" unless $socket -> connected();
$socket -> recv($data);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...