//通过在URL中输入域名,ping的次数例如 :http://localhost:8080/demo2/ping.php?domain=www.google.com&num=3
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>php实现ping功能</title>
</head>
<body>
<?php
class CNetPing
{
public $icmp_socket;
public $request;
// public $request_len;
// var $reply;
public $errstr;
// public $time; //建立连接到发送包得到响应的时间
public $timer_start_time; //开始发送请求包的时间
public $lost_package=0;//默认丢失的包的数量为0
public $recv_package=0;//默认接受到的包的数量为0
public $times=array();
function CNetPing()
{
$this->icmp_socket = socket_create(AF_INET, SOCK_RAW, 1);
//echo " $this->icmp_socket";
socket_set_block($this->icmp_socket);
}
//如果调用时不带可选参数,本函数以 "msec sec" 的格式返回一个字符串,其中 sec 是自 Unix 纪元(0:00:00 January 1, 1970 GMT)起到现在的秒数,msec 是微秒部分。
//字符串的两部分都是以秒为单位返回的
function start_time()
{
$this->timer_start_time = microtime();//microtime() 函数返回当前 Unix 时间戳和微秒数。
//echo "$this->timer_start_time";
}
function get_time($percision = 2)
{
// format start time
list($start_usec, $start_sec) = explode(" ", $this->timer_start_time);//explode() 函数把字符串分割为数组
$start_time = ((float)$start_usec + (float)$start_sec);
// get and format end time
list($end_usec, $end_sec) = explode(" ", microtime());
$end_time = ((float)$end_usec + (float)$end_sec);
$total_time = $end_time - $start_time;
return number_format(1000*$total_time, $percision);
}
/**
* @param $dst_addr
* @param int $timeout
* @param int $percision
* @return bool|string
*/
function ping($dst_addr,$num, $timeout = 5, $percision = 3)
{
// lets catch dumb people
if ((int)$timeout <= 0) $timeout = 5;
if ((int)$percision <= 0) $percision = 3;
/* create the socket, the last '1' denotes ICMP */
// $socket = socket_create(AF_INET, SOCK_RAW, 1);
/* set socket receive timeout to 1 second */
//socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => $timeout, "usec" => 0));
for($i=0;$i<$num;$i++) {
socket_set_option($this->icmp_socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => $timeout, "usec" => 0));
/* connect to socket */
if (socket_connect($this->icmp_socket, $dst_addr, null)) {
echo "socket_connect连接 $dst_addr.成功<br>";
} else {
$this->errstr = "Cannot connect to $dst_addr";
return FALSE;
}
/* 创建一个发送包*/
$this->request = "\x08\x00\x19\x2f\x00\x00\x00\x00\x70\x69\x6e\x67";
/* record start time */
$this->start_time();
socket_send($this->icmp_socket, $this->request, strlen($this->request), 0);
//socket_send($this->icmp_socket,$package,strlen($package),0);
if (@socket_read($this->icmp_socket, 255)) {
//$this->time = $this->get_time($percision);
$this->times[$i]=$this->get_time($percision);
$this->recv_package++;
//return $this->time;
} else {
$this->lost_package++;
$this->errstr = "Timed out";
}
socket_close(icmp_socket);
}
}
}
$domain=$_GET['domain'];
$num=$_GET['num'];
echo "域名:".$domain."<br>";
echo "次数:".$num."<br>";
$percision=3;
$address = gethostbyname($domain);
$ping=new CNetPing();
$ping->ping($address, $num, $percision);
echo"已接受的数据包个数为:$ping->recv_package<br>";
echo"丢失的数据包个数为:$ping->lost_package<br>";
if($ping->recv_package==0){
echo "$ping->errstr";
}else{
sort($ping->times);//系统排序函数。升序函数(从小到大排序)
echo "最短时间为:".$ping->times[0]."ms 最长时间为:".$ping->times[$num-1]."ms 平均时间为:"
.number_format((array_sum($ping->times)/$num),$percision)."ms<br>";//array_sum()计算数组中所有值的和
}
?>
</body>
</html>