2010-03-24 25 views
2

我有一个读取数据的TCP套接字。当读取数据时发生错误时,我返回一个undef(NULL)值。错误信息可能是由格式错误的信息或套接字造成的。有人能告诉我是否有一个返回套接字状态的特定函数吗?如何在Perl中测试TCP套接字状态?

+0

你是什么意思的地位?无论是打开还是关闭? – 2010-03-24 13:57:13

+0

套接字是否处于有效状态,意味着tcp连接处于活动状态 – 2010-03-24 16:10:21

回答

4

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); 
+2

这可能不是你想要的。所有这些调用都会告诉你是初始连接是否成功,或者是否已经通过自己的程序或对等体正常关闭连接。如果连接存在其他问题,例如对等计算机崩溃,或者对等应用程序被锁定,或者由于网络问题而导致对等计算机不可用,则这无助于您。基本上,这不会遇到任何你可能想要捕捉的错误情况。 – 2010-03-24 17:33:15

+0

是的,但在我的使用案例中,我知道消息解码过程无论如何都失败了,我需要的是区分格式错误的消息和断开的套接字。 – 2010-03-25 08:49:14

+0

另外,顺便说一句,连接的呼叫最好与选择功能一起使用。 – 2010-03-25 08:50:01

6

有三种方法可以检测套接字是打开还是关闭,但它们都不是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 closeFIN分组已经到达,则此调用将导致一个0长度同行读取表示一个封闭的插座。这也有助于您的对等应用程序崩溃,因为操作系统将关闭连接并发送FIN。但是,如果您的对等计算机已崩溃或您的对等应用程序已被锁定,则这不会对您有所帮助,因为连接的每一端都保持独立状态。

检测连接断开的第二种方法是通过探测对等点。如果你发送一个长度为0的数据包给你的对端(这应该能够处理)并且应用程序崩溃了,那么你发送第二个0长度的数据包,你的应用程序将得到SIG_PIPE信号indicating a broken pipe

解决此问题的另一种方法是使用应用程序级别的心跳,其中对等方周期性地向对方发送心跳数据包,以指示它们处于活动状态并正常工作。

最后一个选项是使用SO_KEEPALIVE插座选项,尽管这样做的用途有限,因为它只会在大约2小时的非活动状态后检测到插座损坏。

如果您确实必须在连接断开时相当快地知道,那么最可靠的选项可能是应用程序级别的心跳。

+0

实际上它是'MSG_DONTWAIT'标志名称 – AlexM 2015-08-27 08:08:36