PHP实现非阻塞模式的方法分析


Posted in PHP onJuly 26, 2018

本文实例讲述了PHP实现非阻塞模式的方法。分享给大家供大家参考,具体如下:

程序非阻塞模式,这里也可以理解成并发。而并发又暂且可以分为网络请求并发本地并发

先说一下网络请求并发

理论描述

假设有一个client,程序逻辑是要请求三个不同的server,处理各自的响应。传统模型当然是顺序执行,先发送第一个请求,等待收到响应数据后再发送第二个请求,以此类推。就像是单核CPU,一次只能处理一件事,其他事情被暂时阻塞。而并发模式可以让三个server同时处理各自请求,这就可以使大量时间复用。

画个图更好说明问题:

PHP实现非阻塞模式的方法分析

前者为阻塞模式,忽略请求响应等时间,总耗时为700ms;而后者非阻塞模式,由于三个请求可以同时得到处理,总耗时只有300ms。

代码实现

<?php
echo "Program starts at ". date('h:i:s') . "./n";
$timeout = 3;
$sockets = array(); //socket句柄数组
//一次发起多个请求
$delay = 0;
while ($delay++ < 3)
{
  $sh = stream_socket_client("localhost:80", $errno, $errstr, $timeout,
      STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT);
  /* 这里需要稍微延迟一下,否则下面fwrite中的socket句柄不一定能真正使用
    这里应该是PHP的一处bug,查了一下,官方bug早在08年就有人提交了
    我的5.2.8中尚未解决,不知最新的5.3中是否修正
  */
  usleep(10);
  if ($sh) {
    $sockets[] = $sh;
    $http_header = "GET /test.php?n={$delay} HTTP/1.0/r/n";
    $http_header .= "Host: localhost/r/n";
    $http_header .= "Accept: */*/r/n";
    $http_header .= "Accept-Charset: */r/n";
    $http_header .= "/r/n";
    fwrite($sh, $http_header);
  } else {
    echo "Stream failed to open correctly./n";
  }
}
//非阻塞模式来接收响应
$result = array();
$read_block_size = 8192;
while (count($sockets))
{
  $read = $sockets;
  $n = stream_select($read, $w=null, $e=null, $timeout);
  //if ($n > 0) //据说stream_select返回值不总是可信任的
  if (count($read))
  {
    /* stream_select generally shuffles $read, so we need to
      compute from which socket(s) we're reading. */
    foreach ($read as $r)
    {
      $id = array_search($r, $sockets);
      $data = fread($r, $read_block_size);
      if (strlen($data) == 0)
      {
        echo "Stream {$id} closes at " . date('h:i:s') . "./n";
        fclose($r);
        unset($sockets[$id]);
      } else {
        if (!isset($result[$id])) $result[$id] = '';
        $result[$id] .= $data;
      }
    }
  } else {
    echo "Time-out!/n";
    break;
  }
}
//print_r($result);

几点说明:

1、使用stream_socket_client函数链接请求服务器和端口(简便起见这里使用同一地址localhost)。这里不受限于http协议,可广泛用于所有TCP/IP协议。详细内容请参考手册。

2、这里链接成功后通过发送各自http头信息来获取不同响应(这里使用网站根目录下的test.php做服务端)。

3、发送header前需要个微小的延迟,代码中已经做了注释。

CLI模式运行结果:

PHP实现非阻塞模式的方法分析

多运行几次会发现,三次请求结束顺序是无序的。该demo太过简单导致整个过程一秒内已完成,但可以针对三次不同请求做相应延迟,来看出非阻塞时时间复用的效果。

下面再大概说下本地并发

本地并发只能通过语言自己的特性在程序本身实现多任务效果,一般来说现在的语言会通过多线程或多进程的方式来实现。由于PHP不支持多线程,目前只能采用多进程方式,让操作系统来帮助实现本地并发。

至于代码实现,可以通过pcntl扩展(封装fork等进程控制函数,和C语言中使用非常相似,windows下不可用)、 proc_openpopen等方式,方法不止一种,这里就不做详细介绍了。详情可自行搜索“php多进程”进行了解:)

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php+jquery编码方面的一些心得(utf-8 gb2312)
Oct 12 PHP
PHP在获取指定目录下的目录,在获取的目录下面再创建文件,多平台
Aug 03 PHP
jQuery EasyUI API 中文文档 - DateBox日期框
Oct 15 PHP
php文件上传的简单实例
Oct 19 PHP
php+mysqli使用面向对象方式查询数据库实例
Jan 29 PHP
php从数据库查询结果生成树形列表的方法
Apr 17 PHP
Yii扩展组件编写方法实例分析
Jun 29 PHP
如何使用php实现评委评分器
Jul 31 PHP
php仿微信红包分配算法的实现方法
May 13 PHP
PHP实现的下载远程文件类定义与用法示例
Jul 05 PHP
Laravel框架路由和控制器的绑定操作方法
Jun 12 PHP
PHP实现本地图片转base64格式并上传
May 29 PHP
php实现等比例压缩图片
Jul 26 #PHP
PHP输出Excel PHPExcel的方法
Jul 26 #PHP
PHP微信H5支付开发实例
Jul 25 #PHP
php app支付宝回调(异步通知)详解
Jul 25 #PHP
php支付宝APP支付功能
Jul 29 #PHP
PHP多个图片压缩成ZIP的方法
Aug 18 #PHP
PHP上传文件及图片到七牛的方法
Jul 25 #PHP
You might like
谈PHP生成静态页面分析 模板+缓存+写文件
2009/08/17 PHP
修改php.ini以达到屏蔽错误信息并记录日志
2013/06/16 PHP
PHP header()函数常用方法总结
2014/04/11 PHP
php动态生成缩略图并输出显示的方法
2015/04/20 PHP
Smarty使用自定义资源的方法
2015/08/08 PHP
php异常处理捕获错误整理
2019/09/23 PHP
Javascript图像处理—虚拟边缘介绍及使用方法
2012/12/27 Javascript
JS简单实现元素复制示例附图
2013/11/19 Javascript
DIV随滚动条滚动而滚动的实现代码【推荐】
2016/04/12 Javascript
JavaScript变量作用域_动力节点Java学院整理
2017/06/27 Javascript
Angular2仿照微信UI实现9张图片上传和预览的示例代码
2017/10/19 Javascript
JS数组实现分类统计实例代码
2018/09/30 Javascript
iView框架问题整理小结
2018/10/16 Javascript
BootStrap table实现表格行拖拽效果
2018/12/01 Javascript
js作用域和作用域链及预解析
2019/04/11 Javascript
详解基于Wepy开发小程序插件(推荐)
2019/08/01 Javascript
简单了解JavaScript arguement原理及作用
2020/05/28 Javascript
python抓取网页时字符集转换问题处理方案分享
2014/06/19 Python
详解Python命令行解析工具Argparse
2016/04/20 Python
Python常见加密模块用法分析【MD5,sha,crypt模块】
2017/05/24 Python
python3读取excel文件只提取某些行某些列的值方法
2018/07/10 Python
python面试题之列表声明实例分析
2019/07/08 Python
Python画图高斯分布的示例
2019/07/10 Python
centos7中安装python3.6.4的教程
2019/12/11 Python
在python中计算ssim的方法(与Matlab结果一致)
2019/12/19 Python
如何搭建pytorch环境的方法步骤
2020/05/06 Python
python中Ansible模块的Playbook的具体使用
2020/05/28 Python
CSS3 translate导致字体模糊的实例代码
2019/08/30 HTML / CSS
美国唇部护理专家:Sara Happ
2019/06/19 全球购物
在校生党员自我评价
2013/09/25 职场文书
文秘档案管理岗位职责
2014/03/06 职场文书
工程承包协议书范本
2014/09/29 职场文书
公司老总年会致辞
2015/07/30 职场文书
2016三严三实专题教育活动心得体会
2016/01/06 职场文书
2019年行政人事个人工作总结范本!
2019/07/19 职场文书
《狼牙山五壮士》读后感:宁死不屈,视死如归
2019/08/16 职场文书