【发布时间】:2011-01-31 05:30:37
【问题描述】:
我有一个读取数据的 TCP 套接字。当读取数据发生错误时,我返回一个 undef (NULL) 值。错误可能是由格式错误的消息或损坏的套接字引起的。谁能告诉我是否有返回套接字状态的特定函数?
【问题讨论】:
-
状态是什么意思?是打开还是关闭?
-
socket是否处于有效状态,表示tcp连接处于活动状态
我有一个读取数据的 TCP 套接字。当读取数据发生错误时,我返回一个 undef (NULL) 值。错误可能是由格式错误的消息或损坏的套接字引起的。谁能告诉我是否有返回套接字状态的特定函数?
【问题讨论】:
有三种方法可以检测套接字是打开还是关闭,但都不是 100% 完全证明。
第一个是to attempt a read on the socket as follows:
my $ret = recv($sockfd, $buff, 1, MSG_PEEK | MSG_NOWAIT);
如果套接字已经有序关闭,即调用 shutdown for writing or called close 的对等方AND FIN 数据包已到达,则此调用将导致读取长度为 0 的值,指示已关闭套接字。如果您的对等应用程序崩溃,这也有帮助,因为操作系统将关闭连接并发送FIN。但是,如果您的对等计算机已崩溃或您的对等应用程序已锁定,这将无济于事,因为连接的每一端都保持独立状态。
检测断开连接的第二种方法是探测您的对等方。如果您向对等方发送 0 长度数据包(应该能够处理)并且应用程序已崩溃,那么您发送第二个 0 长度数据包,您的应用程序将收到 SIG_PIPE 信号 indicating a broken pipe。
解决此问题的另一种方法是使用应用程序级心跳,其中对等方周期性地向彼此发送心跳数据包,表明它们处于活动状态并且正常运行。
最后一个选项是使用SO_KEEPALIVE 套接字选项,尽管它的用途有限,因为它只会在大约 2 小时不活动后检测到损坏的套接字。
如果您真的必须很快知道连接何时中断,那么最可靠的选择可能是应用程序级心跳。
【讨论】:
MSG_DONTWAIT标志名
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);
【讨论】: