download this file: class.icmp.php view text/plain: class.icmp.php file encoding: UTF-8 [goback]
<?php
##
## this file name is 'class.ping.php'
##
## ping object
##
## [author]
##  - http://linuxchannel.net/
##
## [changes]
##  - 2014.12.09 : timeout tunning
##  - 2008.12.01 : new build
##
## [references]
##  - http://kr.php.net/manual/en/function.socket-create.php
##  - https://github.com/ErikDubbelboer/php-net-tools/  // good
##
## [usage]
##
## [example]
##
class icmp
{
  
// timeout in (seconds, microtime) 
  
public function &ping($host$timeout=array(1,0))
  {
    static 
$port 0;
    static 
$datasize 58// default 58 bytes + 8 = 64 bytes

    
$ident = array(ord('J'), ord('C'));
    
$seq = array(rand(0255), rand(0255));

    
$timeout = array('sec'=>$timeout[0], 'usec'=>$timeout[1]);

    
## 8 bytes of ICMP header data
    
$packet '';
    
$packet .= chr(8); // type = 8 : request
    
$packet .= chr(0); // code = 0
    
$packet .= chr(0); // checksum init
    
$packet .= chr(0); // checksum init
    
$packet .= chr($ident[0]); // identifier
    
$packet .= chr($ident[1]); // identifier
    
$packet .= chr($seq[0]); // seq
    
$packet .= chr($seq[1]); // seq

    
for($i=0$i<$datasize$i++) $packet .= chr(0);

    
$chk icmp::icmpchecksum($packet);

    
$packet[2] = $chk[0]; // checksum init
    
$packet[3] = $chk[1]; // checksum init

    
if(preg_match('/[a-z]/',$host)) $host gethostbyname($host); // to ip

    
if(!$sock = @socket_create(AF_INETSOCK_RAWgetprotobyname('icmp')))
    {
        return array(-
2socket_last_error());
    }

    
//@socket_set_option($sock,SOL_SOCKET,SO_REUSEADDR,1);
    
@socket_set_option($sock,SOL_SOCKET,SO_RCVTIMEO,$timeout); // good idea for blocking mode
    
@socket_set_option($sock,SOL_SOCKET,SO_SNDTIMEO,$timeout);
    
//@socket_set_option($sock,SOL_SOCKET,SO_LINGER,array('l_onoff'=>1,'l_linger'=>5));

    
$time_start microtime();
    @
socket_sendto($sock$packetstrlen($packet), 0$host$port);
    
$time_send microtime();

    
$read   = array($sock);
    
$select = @socket_select($read$write=NULL$except=NULL$timeout['sec'], $timeout['usec']);

    if(
$select === NULL)
    {
        @
socket_close($sock);
        return array(-
1'Select Error');
    }
    else if(
$select === 0)
    {
        @
socket_close($sock);
        return array(-
1'Timeout');
    }

    
$recv '';
    @
socket_recvfrom($sock$recv655350$host$port);
    
$time_stop microtime();
    @
socket_close($sock);

    
$recv unpack('C*'$recv);

    
// ICMP proto = 1
    
if($recv[10] !== 1) return array(-1,'Not ICMP packet');

    
// ICMP response = 0
    
if($recv[21] !== 0) return array(-1,'Not ICMP response');
    if(
$ident[0] !== $recv[25] || $ident[1] !== $recv[26]) return array(-1,"Bad identification number, $ident[0]=$recv[25]$ident[1]=$recv[26]");
    if(
$seq[0] !== $recv[27] || $seq[1] !== $recv[28]) return array(-1,"Bad sequence number, $seq[0]=>$recv[27]$seq[1]=>$recv[28]");

    
$ttt icmp::getms($time_start$time_send);
    
$gtt icmp::getms($time_send$time_stop);
    
$rtt icmp::getms($time_start$time_stop);

    return array(
"$rtt $ttt $gtt",'');
  }

  private function &
icmpchecksum($data)
  {
    
$bit unpack('n*'$data);
    
$sum array_sum($bit);

    if (
strlen($data) % 2)
    {
        
$temp unpack('C*'$data[strlen($data) - 1]);
        
$sum += $temp[1];
    }

    
$sum = ($sum >> 16) + ($sum 0xffff);
    
$sum += ($sum >> 16);

    return 
pack('n*', ~$sum);
  }

  public function &
getms($_start$_end)
  {
    
$end explode(' '$_end);
    
$start explode(' '$_start);

    return 
sprintf('%.3f',(($end[1]+$end[0])-($start[1]+$start[0])) * 1000);
  }

  private function 
error($errstr)
  {
    return 
error_log($errstr,0);
  }

  private function &
socket_info($socket)
  {
    
$opt = array
    (
    
'SO_DEBUG'=>SO_DEBUG,
    
'SO_ACCEPTCONN'=>SO_ACCEPTCONN,
    
'SO_BROADCAST'=>SO_BROADCAST,
    
'SO_REUSEADDR'=>SO_REUSEADDR,
    
'SO_KEEPALIVE'=>SO_KEEPALIVE,
    
'SO_LINGER'=>SO_LINGER,
    
'SO_OOBINLINE'=>SO_OOBINLINE,
    
'SO_SNDBUF'=>SO_SNDBUF,
    
'SO_RCVBUF'=>SO_RCVBUF,
    
'SO_ERROR'=>SO_ERROR,
    
'SO_TYPE'=>SO_TYPE,
    
'SO_DONTROUTE'=>SO_DONTROUTE,
    
'SO_RCVLOWAT'=>SO_RCVLOWAT,
    
'SO_RCVTIMEO'=>SO_RCVTIMEO,
    
'SO_SNDLOWAT'=>SO_SNDLOWAT,
    
'SO_SNDTIMEO'=>SO_SNDTIMEO,
    );

    foreach (
$opt as $k=>$value)
    {
        
$r socket_get_option($socketSOL_SOCKET$value);
        echo 
"$k : \n";
        
print_r($r);
        echo 
"\n";
    }
  }
// end of class
?>