download this file: class.google.php view text/plain: class.google.php file encoding: UTF-8 [goback]
<?php
##
## this file name is 'class.google.php'
##
## ping object
##
## [author]
## - san2(at)linuxchannel.net
##
## [changes]
## - 2014.12.09 : timeout tunning
## - 2012.11.xx : some
## - 2008.12.05 : add more
## - 2008.12.01 : new build
##
## [references]
## - http://kr.php.net/manual/en/function.socket-create.php
## - http://ftp.linuxchannel.net/devel/php_download/
##
## [usage]
##
## [example]
##
class google
{
## googel network latency
##
public function &ping($host)
{
static $port = 0;
static $datasize = 58; // default 58 bytes + 8 = 64 bytes
static $timeout = array('sec'=>0,'usec'=>500000);
$ident = array(ord('J'), ord('C'));
$seq = array(rand(0,255), rand(0,255));
## 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 = google::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_INET, SOCK_RAW, getprotobyname('icmp')))
{
return array(-1, socket_last_error());
}
@socket_set_option($sock,SOL_SOCKET,SO_RCVTIMEO,$timeout); // good idea for blocking mode
@socket_set_option($sock,SOL_SOCKET,SO_SNDTIMEO,$timeout);
$start = microtime();
@socket_sendto($sock, $packet, strlen($packet), 0, $host, $port);
$read = array($sock);
$write = NULL;
$except = NULL;
$select = @socket_select($read, $write, $except, 1, 0);
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, $recv, 65535, 0, $host, $port);
$end = 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");
if($seq[0] !== $recv[27] || $seq[1] !== $recv[28]) return array(-1,"Bad sequence number");
$rtt = google::getms($start, $end);
return array($rtt);
}
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);
}
## google map loading server latency
## default non-blocking mode
##
public function &gethttp($_url, $iporhost='', $rhskip=FALSE)
{
static $bsize = 1048576; // socket send/receive buffer size(Bytes)
static $timeout = array('sec'=>0,'usec'=>500000);
list($host,$ip,$port,$uri) = google::gethostip($_url,$iporhost);
if(!$sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP))
{
return array(-1, socket_last_error());
}
@socket_set_option($sock,SOL_SOCKET,SO_SNDBUF,$bsize);
@socket_set_option($sock,SOL_SOCKET,SO_RCVBUF,$bsize);
@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_nonblock($sock); // set to non-blocking mode
$req = 'GET '.$uri.' HTTP/1.1'."\r\n".
'Host: '.$host."\r\n".
'User-Agent: PHP/google'."\r\n".
'Connection: close'."\r\n". // good idea for blocking mode
"\r\n"; // enf of request header mark
$start = microtime();
$code = google::_connect($sock,$ip,$port,5);
if($code != 1)
{
@socket_close($sock);
return array(-1, "can not connect to $ip:$port");
}
if(!@socket_write($sock,$req))
{
@socket_close($sock);
return array(-1, "can not send request $uri");
}
$header = google::_getheader($sock,1024); // read header
$header = google::_parse_header($header);
if(!$rhskip && $header['error'])
{
@socket_close($sock);
return array(-1, $header['status'].' '.$uri);
}
//$total = $header['content-length']; // total size
//$pg = $debug ? $total : 0; // debug mode with progress
$size = google::_readsize($sock,$bsize); // check bandwidth mode
//google::_readbyall($sock,$buf='',$bsize,$blocking,$pg);
//$size = strlen($buf);
@socket_close($sock);
$end = microtime();
return array(google::getms($start,$end));
}
public function gethostip($_url, $iporhost='')
{
list($nhost,$port,$uri) = $c = google::_parse_url($_url);
if(preg_match('/[a-z]/',$nhost)) $host = $nhost;
else $ip = $nhost;
if($iporhost)
{
if(preg_match('/[a-z]/',$iporhost)) $host = $iporhost;
else $ip = $iporhost;
}
if(!$ip) $ip = gethostbyname($host); // to ip
else if(!$host) $host = $ip; // not good
return array($host,$ip,$port,$uri);
}
## connect to host:port
##
## [return]
## 1 or TRUE : connected
## 0 or FALSE : can't connect
## -1 : connetion time out
##
private function &_connect(&$sock, $host, $port, $timeout=3)
{
$_time = time();
while(1)
{
@socket_connect($sock,$host,$port);
if(@socket_last_error()==56 || @socket_last_error()==106) { return TRUE; break; }
else if((time()-$_time) >= $timeout) { return -1; break; }
}
return FALSE;
}
## read header by socket_read()
## PHP_NORMAL_READ : 1
## PHP_BINARY_READ : 2
##
private function &__readheader(&$sock, $bsize)
{
while($buf = @socket_read($sock,$bsize,PHP_NORMAL_READ))
{
//if(!defined('_RESPONSE_END_')) define('_RESPONSE_END_',microtime());
if(!trim($obuf.$buf))
{
@socket_read($sock,$bsize,PHP_NORMAL_READ); // seek 1 bytes
break; // end of header
}
$rbuf .= $buf; $obuf = $buf;
}
return $rbuf;
}
## read HTTP all headers
##
private function &_getheader(&$sock, $bsize=1024)
{
$stream = array($sock);
while(@socket_select($stream,$write=NULL,$except=NULL,1,0) !== FALSE)
{
//if(!in_array($sock,$stream)) break; // is bug ???
$rbuf = google::__readheader($sock,$bsize);
break; // require
}
return $rbuf;
}
private function &_parse_header($buf)
{
$lines = preg_split('/[\r\n]+/',trim($buf));
$size = sizeof($lines);
$r['status'] = trim($lines[0]);
if(!preg_match(';200 OK;',$lines[0]))
{
$r['error'] = TRUE;
return $r;
}
for($i=1; $i<$size; $i++)
{
$line = trim($lines[$i]);
list($k) = preg_split('/:\s+/',$line);
$r[strtolower($k)] = preg_replace(';^'.$k.':\s+;','',$line);
}
return $r;
}
## only read size, this is a bandwidth test version
##
private function &_readsize(&$sock, $bsize=1048576)
{
$stream = array($sock);
while(@socket_select($stream,$write=NULL,$except=NULL,1,0) !== FALSE)
{
if(!in_array($sock,$stream)) break;
if($tsize = strlen(@socket_read($sock,$bsize)))
{
$rsize += $tsize;
} else break; // good idea, EOF
}
return $rsize;
}
private function &getms($_start, $_end)
{
$end = explode(' ', $_end);
$start = explode(' ', $_start);
return sprintf('%.3f',(($end[1]+$end[0])-($start[1]+$start[0])) * 1000);
}
private function &_parse_url($_url)
{
$url = parse_url(preg_replace(';^(?:http://)*;i','http://',trim($_url)));
$host = $url['host'];
$port = $url['port'] ? $url['port'] : 80;
$uri = $url['path'] ? $url['path'] : '/';
if($url['query']) $uri .= '?'.$url['query']; // add san2@2008.12.01
return array($host,$port,$uri);
}
private function &error($errstr)
{
return error_log($errstr,0);
}
} // end of class
?>