第一步:
首先准备两个文件a.php和b.php,两个文件都放到一台服务器上,同时创建a.txt, 1.txt, 2.txt, 3.txt文件,这几个txt文件都设置777权限
目录机构如下:
其中a.php文件的代码如下:
<?php
class test{
/**
* php异步请求
* @param $host string 主机地址
* @param $path string 路径
* @param $param array 请求参数
* @return string
*/
private static function asyncRequest($host, $path, $param = array())
{
$query = isset($param) ? http_build_query($param) : '';
$port = 80;
$errno = 0;
$errstr = '';
$timeout = 30; //连接超时时间(S)
//打开连接通道
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
//$fp = stream_socket_client("tcp://".$host.":".$port, $errno, $errstr, $timeout);
//echo '<pre>';
//var_dump($query);
//var_dump($fp);
//var_dump($host,$port,$errstr,$timeout);
//die;
if (!$fp) {
var_dump('连接失败');
return '连接失败';
}
if ($errno || !$fp) {
var_dump($errstr);
return $errstr;
}
stream_set_blocking($fp, 0); //非阻塞
stream_set_timeout($fp, 1);//响应超时时间(S)
//通道打开,模拟HTTP请求,http协议标准的换行是\r\n,
//说明: 一般我们用浏览器访问网站(get请求或者post请求)时, 我们并没有写请求头,是因为浏览器自动为我们加上请求头; 但是但我们用代码模仿浏览器发送get/post请求的时候,需要我们自己把请求头加上, 这也是我们为什么写下面这段代码的原因.
$out = "POST " . $path . " HTTP/1.1\r\n";
$out .= "host:" . $host . "\r\n";
$out .= "content-length:" . strlen($query) . "\r\n";
$out .= "content-type:application/x-www-form-urlencoded\r\n";
$out .= "connection:close\r\n\r\n";
$out .= $query;
//http模拟完成,发送给服务器
$result = fwrite($fp, $out);
//接受服务器的返回结果
//$s='';
//while(!feof($fp)){
// $s.=fread($fp,1024);
//}
//echo $s;
fclose($fp);
var_dump('接口调用完毕');
var_dump($result);
//return $result;
}
/**
* 正常接口a.php
* @param $host string 主机地址
* @param $path string 路径
* @param $param array 请求参数
*/
public function a()
{
$param = array(
'name' => 'Jack',
'age' => 30,
'sex' => 'man'
);
$asyncData = $this->asyncRequest('localhost', '/b.php', $param);
echo 'a.php success';
}
}
$m = new test();
$m->a();
b.php代码如下:
<?php
class test{
public function b()
{
set_time_limit(0);
$s = json_encode($_POST);
file_put_contents('./a.txt',$s);
// ignore_user_abort(true);//设置与客户机断开是否会终止执行
// fastcgi_finish_request();//提高请求的处理速度
sleep(30);
echo "耗时30秒";
file_put_contents('./1.txt','第一个时间标记');
sleep(20);
echo "耗时20秒";
file_put_contents('./2.txt','第二个时间标记');
sleep(10);
echo "耗时10秒";
file_put_contents('./3.txt','第三个时间标记');
}
}
$m = new test();
$m->b();
第二步:
通过浏览器地址栏访问: 192.168.30.190/a.php,
第三步:
通过浏览器地址栏访问, 浏览器迅速打印信息(迅速打印信息说明fsockopen()函数非阻塞效果已经生效)如下:
然后迅速的查看a.txt, 1.txt, 2.txt, 3.txt, 4.txt(不断的(每次可以间隔0.5秒)按键盘上的 “ ↑ ” 键、“ Enter ”键,去监测这几个文件是否有数据写入)目录中是否有内容被写入
如下:
可以看到a.txt是迅速被写入内容的, 紧接着随着sleep()函数的的休眠时间的不断流逝, 1.txt, 2.txt, 3.txt文件依次间隔一段时间被写入数据
结论:
通过以上实验, 说明fsockopen()函数中
stream_set_blocking($fp, 0); //非阻塞
的非阻塞效果已经显现了, 请求a.php文件,迅速打印数据, 并未阻塞, 然后通过fsockopen()函数异步发送请求, 去请求b.php中的模拟的耗时任务, 最后将b.php中的耗时任务都执行完毕。
其他说明参考: https://blog.csdn.net/Hiking_Tsang/article/details/70332149