Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

IO::Socket reconnect

by nikita.af (Acolyte)
on Feb 13, 2016 at 21:34 UTC ( [id://1155181]=perlquestion: print w/replies, xml ) Need Help??

nikita.af has asked for the wisdom of the Perl Monks concerning the following question:

Hi all. I wrote a script for my hosts which collects data and send it to a server. Script opens network socket and wait for a connection from monitoring application. After connection my script starts to send data to an open socket. The issue is that if remote side disconnected, script returns "Broken pipe" and die while I suppose it to wait connection again. Could someone help with it ? Here is the snippet:

#!/usr/bin/env perl use 5.010; use warnings; use strict; use Net::Ping; use Getopt::Std; use IO::Socket; my $proto; # ping protocol my $host; # remote host my $bind_addr; # local ip interface to bind my $bind_port; # local port to bind my $monitoring_node; # monitoring status node my $monitoring_name; # cantain formatted remote host name to +insert into a monitoring node my %options=(); # hash to work with options my $result; # ping probe result my $latency; # latency to remote host my $sock; # network sockect object my $agent_socket; # network sockect object my $interval; # delay between checks $|=1; # Getting options getopts("p:h::n:i:s:d:", \%options); sub CheckArgs() { # Checking for non-mandatory options if (defined ($options{p})) { $proto = $options{p}; } else { $p +roto = "tcp"; }; if (defined ($options{i})) { $bind_addr = $options{i}; } else +{ $bind_addr="0.0.0.0"; }; if (defined ($options{s})) { $bind_port = $options{s}; } else +{ $bind_port = "9906"; }; if (defined ($options{d})) { $interval = $options{d}; } else { + $interval = "5"; }; # Checking for mandatory options if (defined ($options{h}) && defined ($options{n})) { $host = $options{h}; $monitoring_node = $options{n}; &Main; } else { &PrintHelp; exit 1; } } sub PrintHelp() { print "Latency monitor v1.5.1\nOptions:\n -p Ping protocol +to use: tcp(default), udp, icmp(requires root)\n -h Destination ho +st. IP or DNS name can be specified. Mandatory option, no have defaul +t value\n -n status node to report. Mandatory option, no default v +alue\n -d Delay between checks in seconds. Default value 5\n -i + IP interface to bind. Default value 0.0.0.0\n -s Socket to bind. +Default value 9906\n"; exit; } sub Main() { # New network socket instance $sock = new IO::Socket::INET ( LocalHost => "$bind_addr", LocalPort => "$bind_port", Proto => 'tcp', Listen => 5, Type => SOCK_STREAM, Reuse => 1 ) or die "Can't create socket: $!\n"; # New ping instance my $ping = Net::Ping->new("$proto") or die "Can't initialize ping: $!\n"; $monitoring_name = $host; $monitoring_name =~ s/\./-/; $agent_socket = $sock->accept(); # Main loop while (42) { ($result,$latency) = $ping->ping($host); $latency *= 1000; $latency =~ s/\.\d+//; print $agent_socket $monitoring_node . ".lmonitor." . +$monitoring_name . ".rtt.value=" . $latency . "\n"; sleep $interval; } $sock->close; } &CheckArgs;

Replies are listed 'Best First'.
Re: IO::Socket reconnect
by golux (Chaplain) on Feb 14, 2016 at 02:57 UTC
    Hi nikita.af,

    Try catching the SIGPIPE signal. Something like:

    my $b_err = 0; $SIG{'PIPE'} = sub { $b_err = 1 }; print $agent_socket $monitoring_node . ".lmonitor." . $monitoring_ +name . ".rtt.value=" . $latency . "\n"; if ($b_err) { # .... Handle the SIGPIPE error }

    will likely work. If a SIGPIPE error happens while printing to the socket, the flag "$b_err" gets set, and you can then handle the error appropriately.

    Oh, one other note -- isn't:

    print $agent_socket "$monitoring_node.lmonitor.$monitoring_name.rtt.v +alue=. $latency .\n";

    a lot easier to read than the original? ;-)

    say  substr+lc crypt(qw $i3 SI$),4,5

      Hi golux, thank you, it seems to be the way I need. Also thanks for the remark, I'll correct it)

Re: IO::Socket reconnect
by NetWallah (Canon) on Feb 14, 2016 at 08:13 UTC
    Check for
    if ( $agent_socket->connected ){ print $agent_socket $monitoring_node . ".lmonitor." . $monitori +ng_name . ".rtt.value=" . $latency . "\n"; }else{ # Your retry logic here }

            "Think of how stupid the average person is, and realize half of them are stupider than that." - George Carlin

      Hi NetWallah, I tried to do it before post the issue here, but unfortunately it doesn't work.

        Could you expand a little on what "it" was that you tried, and what you mean by "doesn't work" - What specific messages did you get ?

        Did it still try to send if the socket was not connected ?

        WHat was your recovery logic ?

                "Think of how stupid the average person is, and realize half of them are stupider than that." - George Carlin

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1155181]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (5)
As of 2024-04-19 16:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found