【问题标题】:AnyEvent->timer not working with AnyEvent::Handle?AnyEvent->计时器不能与 AnyEvent::Handle 一起使用?
【发布时间】:2014-11-03 12:24:31
【问题描述】:

我正在尝试在我的 Catalyst、AnyEvent、Websocket 应用程序中构建超时场景。 为此我正在使用

AnyEvent->timer

应该在几秒钟不活动后调用(没有更多的 WS 帧进入)。

问题是,我的计时器从未执行:

my $w = AnyEvent->timer (after => 3,
                         cb    => sub {
    warn "TIMEOUT!";
});

$self->{server} = Protocol::WebSocket::Handshake::Server->new_from_psgi(
                            $c->req->env) or die $c->log->fatal($!);

$self->{handle} = AnyEvent::Handle->new(
    fh => $c->req->io_fh,
    on_error => sub {
        my ($hd, $fatal, $msg) = @_;
        $clean_up->();
    }
);

die $c->log->fatal("WS Server error: '$_'")
        if $self->{server}->error;

$self->{server}->parse($self->{handle}->fh);
$self->{handle}->push_write($self->{server}->to_string);

$self->{handle}->on_read(sub {
    (my $frame = $self->{server}->build_frame)->append($_[0]->rbuf);

    while (my $frame_msg = $frame->next) {
        ...
    }

定时器回调永远不会被执行。 我的猜测是,计时器在另一个事件循环 (AnyEvent::Handle) 中不起作用?

【问题讨论】:

  • 您能否对不使用 Protocol::WebSocket::Handshake::Server 的问题进行可运行的演示? (例如,它可以从 STDIN 读取,可以从 perl -E'$|=1; say "abc"; sleep 4; say "def"; 管道传输)您的问题是不必要的不​​可访问(除非它与 Protocol::WebSocket::Handshake::Server 相关,在这种情况下您应该提及)。
  • 如果问题中发布的所有代码都在一个函数中,那么一旦该函数退出,$w 就会超出范围,从而取消计时器。

标签: perl websocket catalyst anyevent


【解决方案1】:

您是否真的进入事件循环以处理要处理的计时器?您的代码 sn-p 没有表明这一点。

另外,AnyEvent::Handle 内置了不活动超时:

       timeout => $fractional_seconds
           If non-zero, then this enables an "inactivity" timeout: whenever
           this many seconds pass without a successful read or write on the
           underlying file handle, the "on_timeout" callback will be invoked
           (and if that one is missing, a non-fatal "ETIMEDOUT" error will
           be raised).

           Note that timeout processing is also active when you currently do
           not have any outstanding read or write requests: If you plan to
           keep the connection idle then you should disable the timout
           temporarily or ignore the timeout in the "on_timeout" callback,
           in which case AnyEvent::Handle will simply restart the timeout.

           Zero (the default) disables this timeout.

       on_timeout => $cb->($handle)
           Called whenever the inactivity timeout passes. If you return from
           this callback, then the timeout will be reset as if some activity
           had happened, so this condition is not fatal in any way.

【讨论】:

  • 只是对不活动超时的一个小补充 - 提到它们是上帝,因为它们实际上可能是对提问者问题的解决方案,但我想另外指出,这些超时不同于整体超时。前者可能永远不会触发,因为对方一直在发送数据,而没有发送完成请求所需的正确数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多