Perl localhost的AnyEvent tcp服务器客户端示例在不使用TLS时挂起

Perl localhost的AnyEvent tcp服务器客户端示例在不使用TLS时挂起,perl,anyevent,Perl,Anyevent,在Windows上调试失败的测试时,我根据测试创建了以下脚本: TLS的输出(在取消注释以TLS和TLS\u ctx开头的4行后)为: server\u监听 睡觉。。 正在等待客户端完成。。 客户端连接 服务器\u接受 客户排水管 正在等待服务器完成。。 服务器得到线路 服务器 请注意,在不使用TLS时,不会调用\u connect上的(客户端\u connect在输出中缺失) 即使客户端在不使用TLS时未连接,服务器也会接收数据并打印server-got-line。。。很奇怪 你知道不使

在Windows上调试失败的测试时,我根据测试创建了以下脚本:

TLS的输出(在取消注释以
TLS
TLS\u ctx
开头的4行后)为:

server\u监听
睡觉。。
正在等待客户端完成。。
客户端连接
服务器\u接受
客户排水管
正在等待服务器完成。。
服务器得到线路
服务器
  • 请注意,在不使用TLS时,不会调用\u connect上的
    客户端\u connect
    在输出中缺失)
  • 即使客户端在不使用TLS时未连接,服务器也会接收数据并打印
    server-got-line
    。。。很奇怪

你知道不使用TLS时有什么问题吗?

从外观上看,你不是在从套接字/句柄读取数据。如果不从插座读取数据,就无法检测EOF状况

TLS行为不同的原因是TLS不模拟套接字语义,并且AnyEvent::Handle必须始终读取,即使没有显式读取请求,因此它将立即检测EOF条件

您可以通过添加on_read处理程序来检查这一点,例如,在服务器中的push_read之后或之前:

$hd->push_read (sub { });
在这种情况下,无论是否使用TLS,其行为都应大致相同。

根据:

请注意,与读取队列中的请求不同,一个
on_read
回调 这并不意味着您需要一些数据:如果存在EOF,并且 未完成的读取请求将标记错误。带着
on_read
回调,将调用
on_eof
回调

这提示我需要一个
on_read
回调,以便调用
on_eof
回调。我试图将服务器更改为:

my $server = tcp_server(
    $host,
    undef,   # service: must be either a service name or a numeric port number
             #   (or 0 or undef, in which case an ephemeral port will be used).
             #
    sub { # This is the accept callback..
        my ($fh, $host, $port) = @_;

        say "server_accept";
        my $hd; $hd = AnyEvent::Handle->new(
            fh       => $fh,
            timeout  => 5,
            on_error => sub {
                say "server_error <$_[2]>";
                $server_done->send; undef $hd;
            },
            on_eof   => sub {
                say "server_eof";
                $server_done->send; undef $hd;
            }
        );
        $hd->on_read(sub{ say "server on_read() callback"});
        $hd->push_read (
            line => sub {
                say "server got line <$_[1]>";
            }
        );

    },  # end of accept callback..
    sub {  # This is the prepare callback
        say "server_listen";
        $server_port->send ($_[2]);
   }
);
my$server=tcp\u服务器(
$host,
未定义,#服务:必须是服务名称或数字端口号
#(或0或undef,在这种情况下,将使用临时端口)。
#
这是接受回调。。
我的($fh,$host,$port)=@;
说“服务器接受”;
my$hd;$hd=AnyEvent::Handle->new(
fh=>$fh,
超时=>5,
on_error=>sub{
说“服务器错误”;
$server_done->send;未定义$hd;
},
on_eof=>sub{
说“server_eof”;
$server_done->send;未定义$hd;
}
);
$hd->on_read(sub{say“server on_read()callback”});
$hd->push_-read(
行=>sub{
说“服务器上线”;
}
);
},#接受回调结束。。
sub{#这是prepare回调
说“服务器听”;
$server\u port->send($\u[2]);
}
);
现在输出为:

server_listen
Sleeping..
Waiting for client done..
client_drain
server_accept
Waiting for server done..
server got line <1>
server_eof
server\u监听
睡觉。。
正在等待客户端完成。。
客户排水管
服务器\u接受
正在等待服务器完成。。
服务器得到线路
服务器
所以它起作用了!(我仍然想知道为什么连接上的客户端未运行,即“客户端连接”未显示)。还请注意,由于没有输出行“server on_read()callback”,因此未运行
on_read
回调


另请参见

谢谢您的回答!奇怪的是,只有当我替换你的
$hd->push_read(sub{})时,它才起作用带有
$hd->on_read(sub{})
$hd->push_read (sub { });
my $server = tcp_server(
    $host,
    undef,   # service: must be either a service name or a numeric port number
             #   (or 0 or undef, in which case an ephemeral port will be used).
             #
    sub { # This is the accept callback..
        my ($fh, $host, $port) = @_;

        say "server_accept";
        my $hd; $hd = AnyEvent::Handle->new(
            fh       => $fh,
            timeout  => 5,
            on_error => sub {
                say "server_error <$_[2]>";
                $server_done->send; undef $hd;
            },
            on_eof   => sub {
                say "server_eof";
                $server_done->send; undef $hd;
            }
        );
        $hd->on_read(sub{ say "server on_read() callback"});
        $hd->push_read (
            line => sub {
                say "server got line <$_[1]>";
            }
        );

    },  # end of accept callback..
    sub {  # This is the prepare callback
        say "server_listen";
        $server_port->send ($_[2]);
   }
);
server_listen
Sleeping..
Waiting for client done..
client_drain
server_accept
Waiting for server done..
server got line <1>
server_eof