【问题标题】:How can I test TCP socket status in Perl?如何在 Perl 中测试 TCP 套接字状态?
【发布时间】:2011-01-31 05:30:37
【问题描述】:

我有一个读取数据的 TCP 套接字。当读取数据发生错误时,我返回一个 undef (NULL) 值。错误可能是由格式错误的消息或损坏的套接字引起的。谁能告诉我是否有返回套接字状态的特定函数?

【问题讨论】:

  • 状态是什么意思?是打开还是关闭?
  • socket是否处于有效状态,表示tcp连接处于活动状态

标签: perl sockets tcp


【解决方案1】:

有三种方法可以检测套接字是打开还是关闭,但都不是 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标志名
【解决方案2】:

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

【讨论】:

  • 这可能不是你想要的。所有这些调用都会告诉您初始连接是否成功,或者您自己的程序或对等方是否正常关闭了连接。如果连接存在其他问题,例如对等计算机崩溃、对等应用程序被锁定或对等计算机由于网络问题而无法使用,这将无济于事。基本上,这不会捕获您可能希望捕获的任何错误条件。
  • 没错,但在我的用例中,我知道消息解码过程无论如何都失败了,我需要一种区分格式错误的消息和损坏的套接字的方法。
  • 另外,顺便说一句,connected call 最好与 select 函数结合使用。
猜你喜欢
  • 2015-08-29
  • 2023-03-19
  • 1970-01-01
  • 2014-01-31
  • 1970-01-01
  • 2023-03-19
  • 2013-05-10
  • 2012-05-04
  • 2018-08-01
相关资源
最近更新 更多