对于我来说,我似乎无法弄清楚如何获得一个标准的TCP套接字连接后重新连接断开,尤其是在IO ::异步::环Perl IO :: Socket :: INET + IO :: Async :: Stream在断开连接时重新连接到TCP服务器
一些基本的方面:
#!/usr/bin/perl
use strict;
use warnings;
use Socket;
use IO::Async::Loop;
use IO::Async::Stream;
use IO::Socket;
use Time::HiRes qw(usleep);
# standard event loop
my $loop = IO::Async::Loop->new;
# notification service socket connection; we only write outgoing
my $NOTIFY = IO::Socket::INET->new(
PeerHost => $a_local_network_host,
PeerPort => $comm_port,
Proto => 'tcp',
Type => SOCK_STREAM,
ReuseAddr => 1,
Blocking => 0
) or warn("Can't connect to NOTIFY: $!\n");
setsockopt($NOTIFY, SOL_SOCKET, SO_KEEPALIVE, 1);
# main interface element via IO::Async
my $notifystream = IO::Async::Stream->new(
handle => $NOTIFY,
on_read => sub {
my ($self, $buffref, $eof) = @_;
# here's where we need to handle $eof if the remote goes away
if($eof) {
# i have tried several things here
usleep(200000); # give the remote service some milliseconds to start back up
# process fails if remote is not back up, so i know the timeout is 'good enough' for this test
# attempt to reconnect. have also tried recreating from scratch
$NOTIFY->connect("$a_local_network_host:$comm_port");
# this doesn't seem to have any effect
$self->configure(handle=>$NOTIFY);
}
}
);
$loop->add($notifystream);
# kickstart the event loop
$loop->run;
### -- Meanwhile, elsewhere in the code -- ###
$notifystream->write("data for notification service\n");
在现实中,有很多事情在循环回事。我还有更复杂的方法来测试socket关闭或中断,$ notifystream上的更多错误处理程序,以及重新连接到远程服务的更好的超时/退避,但是这应该显示我正在做的主要关键。
当远程服务器由于任何原因而离开时,我想尝试重新连接它而不会中断系统的其他部分。在大多数情况下,远程发送eof干净,因为它有意重新启动(不是我的选择,只是我必须处理),但我也想处理其他通信错误。
在实践中,上述代码的工作方式就像它的工作原理一样,但远程服务不再接收对$ notifystream的进一步写入调用。没有错误产生,$ notifystream愉快地进一步写入,但他们不被传送到远程。
我有一种感觉,我做错了。我不打算重写应用程序事件循环的其余部分,所以请不要'只使用AnyEvent'类型的响应 - 真正希望更好地了解如何重新连接/重用/重新创建使用的变量(IO :: Socket :: INET和IO :: Async :: Stream)来补偿远程服务器暂时不可用时的情况。
欢迎对此目标提出任何建议或参考。谢谢!
- = - = - = - = -
总结错误我有(并且没有)接收: 如果我不留usleep,基座插座由于将失败的重新连接(或娱乐)远程服务不可用。 如果我试图从头开始重新创建套接字,然后'配置'流,我得到'不能调用未定义的方法sysread这导致我相信套接字没有正确重新创建。 在任何时候,无论我使用当前代码写入套接字的时间多少,流的内置'on_read_error'或'on_write_error'处理程序都会触发,但如果我完全销毁套接字,则会生成一个错误。 套接字似乎仍然是活跃的,我知道它已经关闭,重新连接似乎并没有改变任何东西。没有错误产生,但套接字没有被写入。
是否有不同的语法重新连接到一个IO ::套接字:: INET套接字?到目前为止,调用connect()或重新开始重建似乎是关闭连接的唯一选项,并且都不起作用。
我没有看到任何错误检查?你提到你有他们,他们说什么?你肯定需要“重新启用”重新启动,这些错误将有助于弄清楚什么。 – zdim
我在IO :: Async :: Stream中有'on_read_error','on_write_error'和'on_writeable_stop' - 它们都没有触发。在所有。我也试过/ catch'd所有 - 问题是没有引发错误。它只是不起作用。 – derelict
你尝试重新连接你的'$ NOTIFY'吗?这个问题还不清楚。你可能也可能不需要再向环路添加'(也许重新启动它)。你能澄清你是否尝试过,你能否用这些错误检查方法所说的信息来完成这个问题? – zdim