php:异步请求实现方式有哪些?

前言

最近小编在开发过程中,遇到一些处理操作,并不需要实时返回结果,怎么绕过等待?这个时候我们需要用到异步进行请求,长话短说。

 

一、ajax和img标签

如果是web服务器返回html代码给客户端,我们可以使用一些特殊方法来实现所谓的异步,就是在返回给客户端的HTML代码中,嵌入ajax调用,或者,嵌入一个img标签,src指向要执行的耗时脚本(还有一些类似script标签)。如果客户端不是html代码,其实我们也可以拼接出完整的图片链接(该链接包含处理,然后跳转资源到图片),然后客户端进行展示。

 

二、使用popen()

resource popen ( string command, string mode );
//打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。所以可以通过调用它,但忽略它的输出。

pclose(popen("/home/xinchen/backend.php &", 'r'));

这个方法避免了第一个方法的缺点,并且也很快。但是问题是,这种方法不能通过HTTP协议请求另外的一个WebService,只能执行本地的脚本文件。并且只能单向打开,无法穿大量参数给被调用脚本。
并且如果,访问量很高的时候,会产生大量的进程。如果使用到了外部资源,还要自己考虑竞争。

 

三、使用php的curl扩展

  • curl实现方式的本质是, 设置超时时间为1秒或者n毫秒;
  • 注意: 如果设置超时时间为毫秒,那么要确认,CURL版本>=7.16.2, PHP 版本>=5.2.3.
   /**
     * 使用curl方式发送异步请求, put方式
     */
    public function _curl($url,$params) {
        $ch = curl_init();
        $headers = array("Content-type: application/json;charset='utf-8'",
            "Accept: application/json",
            "Cache-Control: no-cache","Pragma: no-cache");
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"PUT"); //设置请求方式
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);//设置提交的字符串
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);    //设置头信息
        curl_setopt($ch, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($ch, CURLOPT_RETURNTRANSFER , 1 );    //获取的信息以文件流的形式返回
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  //不进行ssl验证
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
        //设置超时时间为1秒,超过1秒则关闭连接
        curl_setopt($ch,CURLOPT_TIMEOUT,1);
        //curl_setopt($ch, CURLOPT_NOSIGNAL, 1);     //注意,毫秒超时一定要设置这个
        //curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200); //超时毫秒,cURL 7.16.2中被加入。从PHP 5.2.3起可使用
        curl_setopt($ch, CURLOPT_HEADER, 0); // 设置是否显示返回头信息  1返回 0不返回
        curl_setopt($ch, CURLOPT_NOBODY, 0); //不想在输出中包含body部分,设置这个选项为一个非零值
        $result = curl_exec($ch);
        curl_close($ch);
        return json_decode($result);
    }

这种方法的缺点就是你必须要等待1秒或者多少毫秒,如果程序执行很快,岂不是白等了?

 

四、使用exec

使用exec执行linux命令,交给后台完成。

例:

exec("nohup curl xxxx.com &");

 

五、使用fsockopen

我们创建了一个基于fsockopen的函数,这个函数中利用fsockopen去访问url,但是在访问时,并不要求获取url显示的内容,而是仅仅发出访问请求,请求到达后马上关闭这个访问,缺点是要拼接header。

get方式

path不需要拼接完整url,只需要路径

<?php

$host = "xxxx.com";//主机地址,如localhost
$path = 'test/test.php';//要请求的url,如http://localhost/test/test.php
// $fp = fsockopen( 'ssl://'.$host , 443, $errno, $errstr, 30);//https请求方式
$fp = fsockopen($host , 80, $errno, $errstr, 30);
if(!$fp){
    exit('请求失败');
}else{
    //拼接header部分
  $header = "GET $path?uid=28CSW6JO3B0N&chat_uid=2ABR5GZPRW6F&gift_id=".json_encode(['uniqid'=>2019110610157975])." / HTTP/1.1\r\n"; 
  $header .= "Host: $host\r\n"; 
  $header .= "Connection: Close\r\n\r\n";
  fwrite($fp, $header);
  // // 输出请求结果(测试时用)
  //  $receive = '';
  //  while (!feof($fp)) 
  //  {
  //   	$receive .= ''.fgets($fp, 128);
  //  }
  //  echo "".$receive;
  fclose($fp);
}

post方式

$host = "xxx.com";//主机地址,如localhost
$path = 'http://xxx.com/test/test.php';//要请求的url
$fp = fsockopen( $host , 80, $errno, $errstr, 30);
if(!$fp){
    exit('请求失败');
}else{
    //要发送的数据
    $data['name'] = '测试';
    $data['desc'] = '测试';
    $post = http_build_query($data);
    $len = strlen($post);

    //拼接header部分
    $header = "POST $path HTTP/1.1\r\n";
    $header .= "Host: $host\r\n";
    $header .= "Content-type: application/x-www-form-urlencoded\r\n";
    $header .= "Connection: Close\r\n";
    $header .= "Content-Length: $len\r\n";
    $header .= "\r\n";
    $header .= $post."\r\n";
    fwrite($fp, $header);
    // //输出请求结果(测试时用)
    // $receive = '';
    // while (!feof($fp)) 
    // {
    //  $receive .= ''.fgets($fp, 128);
    // }
    // echo "".$receive;
    fclose($fp);
}

这种方法是比较好的,但是有一个缺点,你使用后会发现,偶发性请求无效,nginx状态499。

参考:https://blog.csdn.net/panjiapengfly/article/details/103010517  解决上述问题。

 

小结:小编这里说的其实都是比较轻便的方法,如果一些要求比较高的,可以使用队列形式来完成。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值