IruP has asked for the wisdom of the Perl Monks concerning the following question:
2017-10-07 Note added by Athanasius: This node was copied from StackOverflow. See also Re: Extract specify values in file log using perl.
I can't seem to figure out how to get a standard TCP socket connection to reconnect after a disconnect, particularly in the context of an IO::Async::Loop some basics:
#!/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 millisecond +s to start back up # process fails if remote is not back up, so i know the ti +meout is 'good enough' for this test # attempt to reconnect. have also tried recreating from s +cratch $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");
In reality, there are many more things going on in the loop. i also have more sophisticated ways to test for socket closed or broken, further error handlers on the $notifystream, and a better timeout/backoff for reconnecting to the remote service, however this should show the main crux of what i'm doing.
when the remote server goes away for any reason, i'd like to attempt to reconnect to it without disrupting the rest of the system. in most cases the remote sends eof cleanly because it's intentionally rebooting (not my choice, just something i have to deal with), but i'd also like to handle other communication errors as well.
in practice, the above code acts as though it works, however the remote service no longer receives further write calls to the $notifystream. no errors are generated, the $notifystream happily takes further writes, but they are not delivered to the remote.
i have a feeling i'm doing this wrong. i'm not looking to rewrite the rest of the application's event loop, so please no 'just use AnyEvent'-type responses -- really hoping to gain a better understanding of how to reconnect/reuse/recreate the variables in use here (IO::Socket::INET and IO::Async::Stream) to compensate when a remote server is temporarily unavailable.
Any suggestions or references towards this goal are welcome. Thanks!
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Perl IO::Socket::INET + IO::Async::Stream reconnect to TCP server when disconnected
by zentara (Cardinal) on Sep 07, 2017 at 14:47 UTC |