3

这是我的简单服务器。当我运行它并 telnet 到它(端口 5222)并让 telnet 退出它的连接时,为什么我的 on_eof 函数没有被调用?即为什么不是字符串“CATASTROPHE!!!” 打印?

#!/usr/bin/perl

use v5.18;
use warnings;

use EV;
use AnyEvent;
use AnyEvent::Socket;
use AnyEvent::Handle;

our $hdl;

my $server = tcp_server undef, 5222, sub {
    my ($fh) = @_;

    $hdl = AnyEvent::Handle->new(fh => $fh);
    $hdl->on_eof(sub {
        my ($handle) = @_;

        say "CATASTROPHE!!!";
    });
};

EV::run;
4

1 回答 1

2

tl; dr:如果不尝试从套接字读取,则无法检测到 EOF。使用 ->on_eof 或 ->push_read。

长版:

该示例不尝试从句柄中读取任何内容,这就是 AnyEvent::Handle 不尝试读取数据的原因。如果不尝试读取数据,它就无法检测到 EOF(POSIX API 的结果)。

此行为仅在 start_read/stop_read 方法的描述中间接描述:

请注意,当您更改“on_read”回调或推送/取消移动读取回调时,AnyEvent::Handle 将自动为您“start_read”,当“on_read”未设置或没有任何读取时,它会自动为您“stop_read”队列中的请求。

其行为如此的原因是,在基于事件的程序中,在读取数据(在内部完成)和将读取回调排队之间可能存在任何时间。由于接收到不期望的数据是错误的(并且由于不发生错误可能会溢出读取缓冲区,从而导致错误),因此需要某种方法来避免这些错误。

没有请求时不读取数据是一种自动方法,可以避免由于程序没有“足够快”来处理数据而导致的虚假错误: AnyEvent::Handle 在程序做出决定之前不会从套接字读取任何内容如何处理数据。

在您相当不典型的示例中,您对套接字不做任何事情。要检测到 on_eof,您可以调用 ->start_read,但这在现实世界的程序中不太可能有用。

于 2014-06-24T11:11:59.340 回答