Perhaps AnyEvent::FastPing can be of help. Alternatively ...

Being unfamiliar, as well, with AnyEvent I could be wrong but how about using a global table (shared among the timer callbacks - is this allowed? It seems OK.) to store the state of each host like: my $state{'192.168.100.1' => [0, ['success at timexxx with packetsxxx', 'failed at ...', ...]]}; where the first array element is a flag indicating whether a ping is in progress right now or not. And the second element stores the history of ping results, possibly in a finite-size data structure (Queue?).

With the above idea and modifying slightly hippo's code:

use strict; use warnings; use AnyEvent; use AnyEvent::Ping; use Data::Dumper; # separate the hosts wrt their timer groups my @todoList1 = map { "192.168.100." . $_ } (1 .. 2); my @todoList2 = map { "192.168.100." . $_ } (3 .. 4); # a global hash keyed on IPs, => [0,[]]: no pinging now, =>[1,[]]: pin +g in progress # the array ref storing ping history can be a Queue of finite size my $pingState = { map { $_ => [0,[]] } @todoList1, @todoList2 }; my $cv = AnyEvent->condvar; my @timers = ( AnyEvent->timer ( after => 2, interval => 5, cb => sub { warn "Timer 1 at " . AnyEvent->now . "\n"; ping_hosts (1, @todoList1); } ), AnyEvent->timer ( after => 2, interval => 7, cb => sub { warn "Timer 2 at " . AnyEvent->now . "\n"; ping_hosts (2, @todoList2); } ), AnyEvent->timer ( after => 20, cb => sub { warn "Timer 3 at " . AnyEvent->now . "\n"; $cv->send; } ), ); $cv->recv; print "DONE.\n".Dumper($pingState); sub ping_hosts { my ($num, @hosts) = @_; my $ping_timeout = 2; #seconds to wait for response my $ping_attempts = 4; #number of pings to issue, my $ping_pktsize = 32; #packet size of ping my $ping = AnyEvent::Ping->new (packet_size => $ping_pktsize); $ping->timeout ($ping_timeout); #$cv_ping->begin(sub { shift->send($_[0]) }); foreach my $host (@hosts) { if( $pingState->{$host}->[0] == 1 ){ print "ping in progress already to host '$host', skipp +ing till the next timer ...\n"; next } $pingState->{$host}->[0] = 1; # set the "ping in progress" fla +g $ping->ping ( #mock_ping( # emulate the ping $host, $ping_attempts, sub { print "Pinger $num: $host state:" . Dumper ($_[0]) . " +\n"; # store the ping results in global history and remove +the "ping-in-progress" flag push @{$pingState->{$host}->[1]}, $_[0]; $pingState->{$host}->[0] = 0; # ping finished }, # mock_ping extra parameters # $ping_timeout, # 50/100 # probability of a failed ping ); } } # code below is # optional for testing without ping'ing sub mock_ping { my ($host, $attempts, $cb, $timeout, $failure_prob) = @_; # no $attempts, just fail or succeed so many % of times my $started = AnyEvent->time; if( rand()<$failure_prob ){ # simulate a failed ping with lots of delay # so as to coincide with next timer event AEsleep($timeout*3); $cb->([$host, "$started -> fail -> ".AnyEvent->time]); return 0; } else { # a successful ping safely within the timeout AEsleep($timeout/2); # simulate a ping $cb->([$host, "$started -> succ -> ".AnyEvent->time]); return 1; # success ping } } # this is the closest I came to emulating spawning a blocking # ping. Note that using Perl's sleep() is no-go with AnyEvent's timers # AFAIU, re: "It is usually a mistake to intermix alarm and sleep call +s" # and sadly there is no AE::sleep() AFAIK sub AEsleep($) { `sleep $_[0]` }

btw, in my Linux the pinging code needs to be run as root.

bw, bliako


In reply to Re: Implementing AnyEvent::Ping multiple times by bliako
in thread Implementing AnyEvent::Ping multiple times by mmoorreett

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.