你如何知道一个socket客户端已经断开连接?

4

我在使用Perl服务器的套接字时遇到了一些问题。

如何知道一个(非阻塞)客户端已经断开连接? 在C语言中,我习惯于这样做:

if (recv(sock, buff, size, flags) == 0) {
    printf("Client disconnected\n";
}

对于Python或其他语言相应的功能,recv返回-1表示没有数据可用,0表示客户端退出,正数表示可以读取数据。

但是,Perl的recv并不是这样工作的,使用$data = <$sock>似乎没有任何方式可以知道。

是否有(简单的)方法?


你是否正在使用任何异步框架? - creaktive
2
注意:当你说“recv在没有数据可用时返回-1”时,这并不完全正确。当没有数据可用时,recv会返回-1,并将errno设置为EAGAIN或EWOULDBLOCK。但是,也有其他情况下,recv可能会返回-1,主要是由于TCP连接中断的结果(例如,远程对等方崩溃而没有关闭他的套接字,失去Internet连接等)。换句话说,你不应该依赖于recv返回“-1”。始终检查相应的errno以查看是否是可恢复的错误。 - selbie
1个回答

1

你需要查看 perldoc perlioperldoc IO::Socket

#!/usr/bin/perl -w
use IO::Socket;

有很多种方法可以使用非阻塞IO进行组合,从PIPE信号到recv,您可以根据您的需求选择使用哪种方法:

return "Socket is closed" unless $sock->connected;

这就是我如何使用select控制多个套接字。当一个套接字关闭时,我必须将其从列表中移除(仅此而已,因为一旦断开连接,套接字就不存在了,所以没有必要再次关闭它们):

unless (eval {$group{$grp}->{'socket'}->connected}) {
    delete $group{$grp}->{'socket'};
    return 0;
};

eval 可以防止对已断开的套接字进行错误尝试,从而避免脚本出现 socket io 错误

希望这可以帮到你!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接