目录
前文
自从[udpate]php ping ipv4 by socket后,我就一直思考socket_sendto + socket_select + socket_recvfrom 与 socket_connect + socket_send + socket_read 之间的区别,两个方案有何不同,有什么差别呢。
socket_read 和 socket_recv 和 socket_recvfrom 区别
socket_read 和 socket_recv
socket_recv returns the number of bytes received socket_read returns the data that has been received
With socket_recv you can read bytes from the buffer AND know how many bytes have been recevied. With socket_read you can only read a specific amount of data from the buffer
socket_recv 和 socket_recvfrom
socket_recv — Receives data from a connected socket
socket_recvfrom — Receives data from a socket whether or not it is connection-oriented
单次ping测试代码
直接写2个版本,用ping来测试一波。
源码
socket_read
<?php
$t = microtime(1);
$host = 'baidu.com';
$type = "\x08";
$code = "\x00";
$checksum = "\x00\x00";
$identifier = "\x00\x00";
$seq_number = "\x00\x00";
$package = $type . $code . $checksum . $identifier . $seq_number . '';
$checksum = calculateChecksum($package);
$package = $type . $code . $checksum . $identifier . $seq_number . '';
if ($socket = socket_create(AF_INET, SOCK_RAW, 1)) {
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array(
'sec' => 0,
'usec' => 1000*1000,
));
socket_connect($socket, $host, 0);
$start = microtime(true);
socket_send($socket, $package, strlen($package), 0);
if (socket_read($socket, 255) !== false) {
$latency = microtime(true) - $start;
$latency = round($latency * 1000, 4);
}
else {
$latency = false;
}
}
else {
$latency = false;
}
socket_close($socket);
echo $latency.PHP_EOL;
echo microtime(1)-$t;
function calculateChecksum($data) {
if (strlen($data) % 2) {
$data .= "\x00";
}
$bit = unpack('n*', $data);
$sum = array_sum($bit);
while ($sum >> 16) {
$sum = ($sum >> 16) + ($sum & 0xffff);
}
return pack('n*', ~$sum);
}
socket_recvfrom
<?php
$t = microtime(1);
$host = 'baidu.com';
$type = "\x08";
$code = "\x00";
$checksum = "\x00\x00";
$identifier = "\x00\x00";
$seq_number = "\x00\x00";
$package = $type . $code . $checksum . $identifier . $seq_number . '';
$checksum = calculateChecksum($package);
$package = $type . $code . $checksum . $identifier . $seq_number . '';
if ($socket = socket_create(AF_INET, SOCK_RAW, 1)) {
$start = microtime(true);
socket_sendto($socket, $package, strlen($package), 0, $host, 0);
$latency = false;
$read = [$socket];
$write = null;
$except = null;
if($select = socket_select($read, $write, $except, 0, 1000 * 1000)){
if (socket_recvfrom($socket, $recv, 255, 0, $r_host, $r_port)) {
$latency = microtime(true) - $start;
$latency = round($latency * 1000, 4);
}
}
}
else {
$latency = false;
}
socket_close($socket);
echo $latency.PHP_EOL;
echo microtime(1)-$t;
function calculateChecksum($data) {
if (strlen($data) % 2) {
$data .= "\x00";
}
$bit = unpack('n*', $data);
$sum = array_sum($bit);
while ($sum >> 16) {
$sum = ($sum >> 16) + ($sum & 0xffff);
}
return pack('n*', ~$sum);
}
结果
ping 3 times |
ping avg |
spend avg |
socket_read |
50.66436667 |
0.058893681 |
socket_recvfrom |
58.74896667 |
0.059391737 |
- 代码运行时间并没有太大差别
- ping值socket_recvfrom则会稍微偏大,不确定是否有参考意义,实际的话,返回的ping值波动还是比较大的。
参考
PHP socket_recv and socket_read