1

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

4

1 回答 1

1

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

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

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

于 2014-04-30T18:00:42.230 回答