断开连接时,perl io :: socket :: inet io :: async :: stream重新连接到



对于我的一生,我似乎无法弄清楚如何获得标准的TCP插座连接以在断开连接后重新连接,尤其是在IO :: async的背景下::loop

一些基础知识:

#!/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 servicen");

实际上,循环中还有更多事情发生。我也有更复杂的方法来测试套接字关闭或损坏,在$ NotifyStream上进行了更多错误处理程序,以及重新连接到远程服务的更好超时/退缩,但是这应该显示我正在做的事情的主要症状。/p>

出于任何原因远程服务器消失时,我想尝试重新连接它而不会破坏系统的其余部分。在大多数情况下,遥控器会干净地发送EOF,因为它是故意重新启动的(不是我的选择,只是我必须处理的事情),但我也想处理其他通信错误。

实际上,上面的代码就像起作用一样,但是远程服务不再接收到$ NotifyStream的进一步拨打电话。没有产生错误,$ NotifyStream愉快地需要进一步写入,但没有交付给遥控器。

我感觉自己做错了。我不想重写应用程序的事件循环的其余部分,所以请不要"只使用AnyEvent"型响应 - 真的希望更好地了解如何重新连接/重复使用/重新创建此处使用的变量(IO):: socket :: inet and io :: async :: stream)何时暂时不可用。

欢迎对此目标提出任何建议或参考。谢谢!

- = - = - = - = -

总结我(也没有)收到的错误:如果我不留下usleep,则基本插座的重新连接(或娱乐)将由于不可用而失败。如果我尝试从头开始重新创建套接字,然后"配置"流,我会得到"无法在Undefined上调用方法SysRead",这使我相信插座无法正确重新创建。无论我用当前的代码写入多少,我都不会在" on_read_error"或'on_write_error'处理器上构建的流中所内置的流程,尽管如果我完全销毁插座,这些都会产生错误。我知道它已经关闭后,插座似乎仍然活跃,并且重新连接似乎并没有改变任何东西。没有产生错误,但插座没有被写入。

是否有不同的语法可以重新连接到IO :: socket :: inet套接字?到目前为止,从头开始呼叫 -> connect()或重建似乎是封闭连接的唯一选项,也似乎都没有用。

您根本无法多次连接现有套接字。您只能关闭插座并创建一个新的套接字。这与io :: socket :: inet,io :: async ::流甚至perl无关,但这就是插座API的工作方式。

详细说明:本地插座实际上永远不会断开连接,即,它仍然配置为从特定的本地IP地址和端口以及特定地址和端口发送数据。只是,由于基础TCP连接被打破或关闭(即交换的FIN),因此发送的发送将不再起作用。由于没有API可以解开和取消连接套接字,因此唯一的方法是将其关闭并创建一个新的,该新套接字是未结合和无连接的新方法,直到调用连接为止。然后,这个新的套接字可能会或可能不会获得与上一个文件描述符相同的文件描述符。

最新更新