浏览器和服务器之间是通过 HTTP 协议进行连接通讯的。这是一种基于请求和响应模型的协议。浏览器通过 URL 向服务器发起请求,Web服务器接收到请求,执行一段程序,然后做出响应,发送相应的html代码给客户端。
这就有了一个问题,Web 服务器执行一段程序,可能几毫秒就完成,也可能几分钟都完不成。如果程序执行缓慢,用户可能没有耐心等下去,就关闭浏览器了。而有的时候,我们更本不关心这些耗时的脚本的返回结果,但却还要等他执行完返回,才能继续下一步。比如说有段代码需要对数据库做操作,需要耗费一定时间,但是并不需要从执行结果中获取数据,也就是说希望这一步操作可以跳过而另开线程执行。而这可以通过异步来实现。
在返回给客户端的HTML代码中,嵌入AJAX调用,或者,嵌入一个img标签,src指向要执行的耗时脚本。但是缺点是,一般来说Ajax都应该在onLoad以后触发,也就是说,用户点开页面后,就关闭,那就不会触发我们的后台脚本了。而使用img标签的话,这种方式不能称为严格意义上的异步执行。用户浏览器会长时间等待php脚本的执行完成,也就是用户浏览器的状态栏一直显示还在load。
使用curl和sock生成一个新的请求。使用curl比较方便,不过至少需要延时1秒;sock需要自己写http请求头,但可以直接挂掉不耗时。
<?php
$op = $_GET['op']??'asynchronous';
$start = time();
echo 'the demo of asynchronous'."<br/>";
if($op == 'asynchronous'){
sleep(5);
/*$file = fopen('./dmo.txt','w+');
fwrite($file,rand(0,100));
fclose($file);*/
}elseif($op == 'curl'){
$curl = curl_init();
$url = "www.demo.php7.com";
$data = array("op"=>'asynchronous');
curl_setopt($curl,CURLOPT_URL,$url);
curl_setopt($curl,CURLOPT_POST,true);
curl_setopt($curl,CURLOPT_POSTFIELDS,$data);
curl_setopt($curl,CURLOPT_TIMEOUT,1);
curl_exec($curl);
curl_close($curl);
}elseif($op == 'sock'){
$host = 'www.demo.php7.com';
$port = '80';
$link = fsockopen($host,$port);
define('CRLF',"\r\n");
//请求行
$req = 'POST /index.php HTTP/1.1'.CRLF;
//请求头
$req.='HOST:www.demo.php7.com'.CRLF;
$req.='User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36'.CRLF;
$req.='Connection:keep-alive'.CRLF;
//post特殊请求头
$arr = array('op'=>"asynchronous");
$len = http_build_query($arr);
$req.='Content-Length:'.strlen($len).CRLF;
//echo $len.strlen($len) ;die;
$req.='Content-Type:application/x-www-form-urlencoded'.CRLF;
//空行表结束
$req.=CRLF;
//请求主体
$req.=$len;
//发送请求
fwrite($link,$req);
//处理响应数据
/*while(!feof($link)){
echo fgets($link,1024);
}*/
//断开连接
fclose($link);
// sleep(3);
}
$end = time();
echo $end - $start;