客户端使用HTTP::守护程序超时时停止处理



有没有办法让HTTP::Daemon以某种方式检测客户端何时断开连接(例如因为超时(,然后自行终止连接?

现在,我是这样写我的服务器:

my $response;
try {
    local $SIG{ALRM} = sub { die __TIMEOUT__ };
    alarm 180;
    &process_query;
    alarm 0;
    $response = new HTTP::Response(200);
}
catch {
    if ( $_ eq __TIMEOUT__ ) {
        $response = new HTTP::Response(504);
    }
    else {
        $response = new HTTP::Response(500);
    }
};
$client->send_response($response);

这只是假设客户端将在180秒后放弃,这可能是真的,也可能不是真的。只要客户一直在等待响应,我就愿意继续处理,但时间不会更长。

通常,只要您在处理数据(单线程(,它就不会检查文件描述符,因此它不会检测到问题。我看到以下选项:

  • process_query内部不时检查$client套接字是否可使用IO::Select或类似程序读取。可读性可以是客户端关闭连接或发送更多数据,例如HTTP管道。您可以尝试使用recvMSG_PEEK检查是否有数据或eof(例如,客户端关闭(,但您将无法检测到后面是否有更多的数据,因为在获得eof之前,您必须先读取数据
  • 如果您在UNIX上,您可以使用一个很少使用的功能:使用fcntl($client,F_SETOWN,$$),如果$client套接字上有新事件,您可以让内核向您发送SIGIO信号。但是我上一次使用这个Perl时并没有正确处理它,我不得不通过显式调用fcntl-系统调用:syscall(SYS_fcntl,fileno($client),F_SETOWN,$$);来解决它。一旦设置好,就可以像现在处理ALRM一样处理IO信号

在任何情况下:来自客户端的eof仅意味着客户端将不再写入(请求结束(。它可能仍然愿意读取您的数据(单方面关闭(。只有在发送数据并获得SIGPIPE后,您才能知道客户端是否关闭以进行读取。没有办法绕过它,这就是带有BSD套接字的TCP的工作方式。

最新更新