目录
前文
昨天在[测试]socket_read和socket_recvfrom 单次ping中,简单测试了socket_read和socket_recvfrom 在发起单次ping请求时的差异,结论是几乎没有差别。随后又搞了[Multiple and faster]php ping ipv4 by socket,大概实现了批量ping。今天测试和记录下我的测试结果。
测试代码
xfping具体代码可以到Xxx-Bin/php-scoket-ping-Ipv4 xfping
(xfping::init())
->setDebug(0)
->setCallbackDnsError(function($host){
echo 'DnsError :'.$host.PHP_EOL;
})
->setCallbackTimeOut(function($ip){
echo 'timeout :'.$ip.PHP_EOL;
})
->setCallbackOneIp(function($ip,$ret){
echo formet($ip,$ret).PHP_EOL;
})
->setCallbackSingle(function($ip,$seq,$t){
echo 'from ip='.$ip.' seq='.$seq.' t_ms='.($t*1000).PHP_EOL;
})
->setCallback(function ($ret,$t){
echo 'ret '.PHP_EOL;
foreach ($ret as $ip=>$r){
echo formet($ip,$r).PHP_EOL;
}
echo 'total time_ms '.$t;
})->doit($host_list,4,1250,50);
xfping by socket_read
部分修改的代码
148a148
> socket_connect($this->sock, $ip, 0);
150c150
< socket_sendto($this->sock, $packet, strlen($packet), 0, $ip, $port);
> socket_send($this->sock, $packet, strlen($packet), 0);
186c186,187
< while($r = socket_recvfrom($sock, $recvc, 65535, 0, $r_ip, $r_port)){
> while($recvc = socket_read($sock, 65535, 0)){
> // while($r = socket_recv($sock, $recvc,65535, 0)){
190a192
> $r_ip = implode('.',[$recv[13],$recv[14],$recv[15],$recv[16]]);
- 用 socket_connect + socket_send 替换 socket_sendto
- 用 socket_read 或 socket_recv 替换 socket_recvfrom
- socket_read 返回的是 内容,socket_recv 和 socket_recvfrom 返回的是接收长度
- socket_read 和 socket_recv 只能从icmp包中获取,报文格式见ipv4 ICMP 报文
测试结果
$host_list = ‘127.0.0.2;192.168.2.1;127.0.0.1’;
输出信息
ip=127.0.0.2 send=4 recive=4 loss=0.00% min=0.17ms max=0.19ms avg=0.18ms
ip=127.0.0.1 send=4 recive=4 loss=0.00% min=0.16ms max=0.20ms avg=0.18ms
ip=192.168.2.1 send=4 recive=4 loss=0.00% min=2.10ms max=2.58ms avg=2.37ms
total time_ms 663.00201416016
ip=127.0.0.1 send=4 recive=4 loss=0.00% min=0.17ms max=0.26ms avg=0.19ms
ip=192.168.2.1 send=4 recive=4 loss=0.00% min=2.21ms max=2.58ms avg=2.36ms
ip=127.0.0.2 send=4 recive=4 loss=0.00% min=0.17ms max=0.25ms avg=0.18ms
total time_ms 663.75303268433
ip=127.0.0.1 send=4 recive=4 loss=0.00% min=0.18ms max=0.26ms avg=0.20ms
ip=192.168.2.1 send=4 recive=4 loss=0.00% min=2.25ms max=3.62ms avg=2.57ms
ip=127.0.0.2 send=4 recive=4 loss=0.00% min=0.19ms max=0.22ms avg=0.20ms
total time_ms 669.54493522644
发现
没啥区别
$host_list = ‘127.0.0.2;baidu.com;127.0.0.1’;
输出信息
ip=127.0.0.1 send=4 recive=4 loss=0.00% min=0.16ms max=0.22ms avg=0.18ms
ip=127.0.0.2 send=4 recive=4 loss=0.00% min=0.17ms max=0.20ms avg=0.19ms
ip=220.181.38.148 send=4 recive=2 loss=50.00% min=61.16ms max=83.08ms avg=72.12ms
total time_ms 2037.162065506
ip=127.0.0.2 send=4 recive=4 loss=0.00% min=0.16ms max=0.19ms avg=0.17ms
ip=127.0.0.1 send=4 recive=4 loss=0.00% min=0.16ms max=0.17ms avg=0.17ms
ip=220.181.38.148 send=4 recive=2 loss=50.00% min=61.58ms max=61.90ms avg=61.74ms
total time_ms 2037.605047226
ip=220.181.38.148 send=4 recive=4 loss=0.00% min=62.35ms max=66.49ms avg=63.58ms
ip=127.0.0.1 send=4 recive=4 loss=0.00% min=0.18ms max=0.23ms avg=0.22ms
ip=127.0.0.2 send=4 recive=4 loss=0.00% min=0.18ms max=0.20ms avg=0.19ms
total time_ms 675.93193054199
发现
在多ip同时ping时,按找测试代码的写法,ping 间隔事件设置为50ms 小于ping baidu(平均 60 ms 延迟)时,socket_read和socket_recv经常会收不到包,而socket_recvfrom可以稳定收到回包。
- 原因
使用 socket_connect 连接同个$socket但是更改ip 的话,会关闭之前的连接。如果在ping间隔内没收到,则可能被下个socket_connect 连接关闭而导致收不到数据,这也就是上面会出现丢包的原因。
socket_read 代码在修改
if(empty($this->sock[$ip])){
$this->sock[$ip] = socket_create(AF_INET, SOCK_RAW, getprotobyname('icmp'));
socket_set_nonblock($this->sock[$ip]);
}
socket_connect($this->sock[$ip], $ip, 0);
$this->ping_time_start[$key] = ['t'=>microtime(1),'k'=>$key,'ip'=>$ip];
socket_send($this->sock[$ip], $packet, strlen($packet), 0);
再测试
$host_list = ‘127.0.0.2;baidu.com;127.0.0.1’;
输出信息
ip=127.0.0.1 send=4 recive=4 loss=0.00% min=0.17ms max=0.19ms avg=0.18ms
ip=220.181.38.251 send=4 recive=4 loss=0.00% min=60.94ms max=63.93ms avg=61.95ms
ip=127.0.0.2 send=4 recive=4 loss=0.00% min=0.16ms max=0.59ms avg=0.24ms
total time_ms 686.0179901123
memory_get_peak_usage:530312
memory_get_usage:530312
ip=127.0.0.1 send=4 recive=4 loss=0.00% min=0.13ms max=0.17ms avg=0.15ms
ip=127.0.0.2 send=4 recive=4 loss=0.00% min=0.16ms max=0.22ms avg=0.20ms
ip=220.181.38.251 send=4 recive=4 loss=0.00% min=60.41ms max=61.55ms avg=61.15ms
total time_ms 669.29697990417
memory_get_peak_usage:589600
memory_get_usage:589600
ip=127.0.0.2 send=4 recive=4 loss=0.00% min=0.20ms max=0.32ms avg=0.23ms
ip=127.0.0.1 send=4 recive=4 loss=0.00% min=0.14ms max=0.21ms avg=0.16ms
ip=220.181.38.251 send=4 recive=4 loss=0.00% min=60.49ms max=61.29ms avg=60.82ms
total time_ms 682.03282356262
memory_get_peak_usage:589160
memory_get_usage:589160
发现
- socket_read丢包的问题确解决了
- ping 延迟50ms时,速度上差距不大,而socket_read内存上却具有优势,另外再给一组ping100次的数据,可以得到差不多的结论。
- |
total time_ms |
memory |
socket_read |
18362.117052078 |
563496 |
socket_recvfrom |
18354.851007462 |
632624 |
如果把ping延迟改为5ms,ping 10次
- |
total time_ms shuffle_ip_list |
memory |
time_ms dont shuffle_ip_list |
memory |
socket_read |
488.27600479126 |
530312 |
455.3849697113 |
530312 |
socket_recvfrom |
457.83400535583 |
591192 |
444.7181224823 |
591448 |
发现
在ping延迟减低的情况下,socket_recvfrom 则会快一丢丢。内存方面还是socket_read好点。
结论
没太大差别,更推荐socket_read