http://qs1969.pair.com?node_id=430975
Category: Networking Code
Author/Contact Info Kurt Kincaid (sifukurt@yahoo.com)
Description: At work, we've got some fairly strict firewall rules. Specifically, I can't ping outside addresses. This has got in my way many times. Plus, we're almost exclusively a Windows shop and the Windows ping utility irritates me to no end. Put all those things together, and I finally decided to do put together a simple script that will allow me to work around the problem. By default, it does a TCP ping to a specified host on port 80. You can override this behavior from the command line. I've given it to several of the people I work with and they've found it useful. I hope you will, too.

UPDATE: I apologize for the license issue with the original post. That wasn't intended to be included. This was done for when I was handing it around at work. There was a rash of people taking code that other people had written and passing it off as their own to the CIO. Those of us who were bitten by such behavior were forced to start using restrictive licenses for things used at work. I sincerely apologize. That wasn't, never has been, and never will be my intent for things posted here. It rather defeats the purpose. As to why it was written instead of using some other pre-existing tool, several reasons. First, simply for the fun of writing something. I enjoy it. It makes me happy. Second, since I intended for other people I worked with to use it, I wanted to keep it simple and I wanted its behavior to closely mimic that of "ping." Again, I apologize for the licese snafu.
#!/usr/bin/perl

#---------------------------------------------------------------------
+----#
# Ping2
#       Date Written:   11-Feb-2005 07:54:34 PM
#       Last Modified:  14-Feb-2005 04:26:29 PM
#       Author:         Kurt Kincaid
#       Copyright (c) 2005, Kurt Kincaid
#           All Rights Reserved
# This script may be modified and/or redistributed
# under the same terms as Perl itself.
#
#---------------------------------------------------------------------
+----#

use Net::Ping;
use Getopt::Long;
use Time::HiRes qw/ usleep /;
use Socket;
use strict;
use vars qw/ $help $proto $count $wait $p $ret $duration $ip $port $ti
+meout
             $host $ip $iterations $size $wait $total $rx $failed $Sig
+nal
             $VERSION $UPDATE /;

$SIG{ INT } = sub {
    $Signal++;
    Stats();
    exit;
};

GetOptions( 'help' => \$help, 'proto=s' => \$proto, 'count=i' => \$cou
+nt, 'timeout=i' => \$timeout,
            'wait=i' => \$wait, 'size=i' => \$size, 'port=i' => \$port
+ );
$VERSION   = "1.1";
$UPDATE    = "14-Feb-2005 04:26:29 PM";
$proto   ||= "tcp";
$wait    ||= 1000;
$size    ||= 64;
$port    ||= 80;
$timeout ||= 2;
$host = $ARGV[ -1 ];
$wait *= 1000;
if ( $size > 1024 ) { $size = 1024 }
unless( $host ) {
    $help = 1;
}

if ( $help ) {
    print qq~Ping2 v$VERSION ($UPDATE)
Usage ping2 [OPTION]... HOST

Options:
  --count NUM   Number of packets to send.
  --help        This help text.
  --port XX     Port to which connection attempt is made. Default is 8
+0.
  --proto XX    Protocol to use. Options include tcp, icmp, udp, strea
+m,
                and syn. Default is tcp.
  --size SIZE   Size, in bytes, of packet to send. Maximum is 1024.
                Default is 64.
  --timeout XX  Timeout in milliseconds to wait for each reply. Defaul
+t is
                2000 ms (2 seconds).
  --wait XX     How long to wait in milliseconds between sending packe
+ts.
                Default is 1000 ms (1 second).

Report bugs to Kurt Kincaid (sifukurt\@yahoo.com)
~;
    exit;
}

if ( $host =~ /[a-zA-Z]/ ) {
    my $resp = inet_aton( $host );
    if ( $resp ) {
        $ip = inet_ntoa( $resp );
    }
    do { print "Unable to resolve hostname.\n"; exit; } unless $ip;
} else {
    $ip = $host;
}

$p = Net::Ping->new( $proto, $timeout, $size );
$p->hires();
$p->{ port_num } = $port;
my( $hi, $lo );
$rx = 0;
print( "Pinging $host ($ip) on port $port: $size bytes of data.\n" );
while( 1 ) {
    if ( $Signal ) {
        exit;
    }
    ( $ret, $duration, $ip ) = $p->ping( $host );
    $iterations++;
    $duration *= 1000;
    if ( $ret ) {
        if ( $hi eq "" && $lo eq "" ) {
            $hi = $duration;
            $lo = $duration;
        }
        if ( $duration > $hi ) {
            $hi = $duration;
        }
        if ( $duration < $lo ) {
            $lo = $duration;
        }
        $total += $duration;
        $rx++;
        my $dur = sprintf( "%.5f", $duration );
        print( "$size bytes from $ip: seq=$iterations time=$dur ms\n" 
+);
    } else {
        $failed++;
        print( "Request timed out.\n" );
    }
    if ( $iterations == $count ) { Stats() }
    usleep( $wait );
}

sub Stats {
    $Signal++;
    local $SIG{ __DIE__ } = '';
    my( $per, $avg, $time );
    $per  = sprintf( "%.2f", ( $failed / $iterations ) * 100 );
    if ( $rx ) {
        $avg  = $total / $rx;
    } else {
        $avg = 0;
    }
    $avg     = sprintf( "%.5f", $avg );
    $time    = sprintf( "%.5f", $total );
    $hi      = sprintf( "%.5f", $hi );
    $lo      = sprintf( "%.5f", $lo );
    print qq~--- $ip ping2 statistics ---
$iterations packets transmitted, $rx packets received, $per\% packet l
+oss
round-trip (ms) min/avg/max = $lo/$avg/$hi
~;
    $p->close();
    undef $p;
    exit;
}