当客户端使用HTTP :: Daemon超时时停止处理

时间:2014-04-30 17:28:22

标签: perl timeout http-daemon

有没有办法让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秒后放弃,这可能是也可能不是。只要客户端一直等待响应,我想继续处理,但不会更长。

1 个答案:

答案 0 :(得分:1)

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

  • 如果使用process_query或类似内容可以读取$client套接字,请在IO::Select内查看。可读的可以是客户端关闭连接或者它发送更多数据,例如HTTP流水线。您可以尝试使用recvMSG_PEEK检查是否有数据或eof(例如客户端关闭),但是您将无法检测是否有更多数据后跟eof,因为您首先拥有在获得eof之前阅读数据。
  • 如果您使用的是UNIX,则可以使用很少使用的功能:如果fcntl($client,F_SETOWN,$$)套接字上有新事件,您可以使内核向您发送SIGIO信号。但是我最后一次使用这个Perl时没有正确处理它,我不得不通过显式调用$client - syscall:fcntl来解决它。设置完成后,您可以像处理syscall(SYS_fcntl,fileno($client),F_SETOWN,$$);一样处理IO信号。

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