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之字符串变相相减的代码
Mar 19 PHP
PHP 配置文件中open_basedir选项作用
Jul 19 PHP
PHP 循环列出目录内容的函数代码
May 26 PHP
php全局变量和类配合使用深刻理解
Jun 05 PHP
php导出word格式数据的代码实例
Nov 25 PHP
支持中文和其他编码的php截取字符串函数分享(截取中文字符串)
Mar 13 PHP
php文件下载处理方法分析
Apr 22 PHP
PHP中检索字符串的方法分析【strstr与substr_count方法】
Feb 17 PHP
PHP清除缓存的几种方法总结
Sep 12 PHP
PHP addslashes()函数讲解
Feb 03 PHP
PHP PDO数据库操作预处理与注意事项
Mar 16 PHP
PHP中number_format()函数的用法讲解
Apr 08 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
如何开发一个虚拟域名系统
2006/10/09 PHP
PHP中对用户身份认证实现两种方法
2011/06/04 PHP
php和javascript之间变量的传递实现代码
2012/12/19 PHP
php中strstr、strrchr、substr、stristr四个函数的区别总结
2014/09/22 PHP
php支付宝接口用法分析
2015/01/04 PHP
PHP测试框架PHPUnit组织测试操作示例
2018/05/28 PHP
thinkPHP框架通过Redis实现增删改查操作的方法详解
2019/05/13 PHP
Jquery.addClass始终无效原因分析
2013/09/08 Javascript
Textarea根据内容自适应高度
2013/10/28 Javascript
js+css实现超简洁的二级下拉菜单效果代码
2015/09/07 Javascript
详解JavaScript中数组的reduce方法
2016/12/02 Javascript
微信小程序 wx.uploadFile在安卓手机上面the same task is working问题解决
2016/12/14 Javascript
js实现带三角符的手风琴效果
2017/03/01 Javascript
jquery中$.fn和图片滚动效果实现的必备知识总结
2017/04/21 jQuery
解决vue 引入子组件报错的问题
2018/09/06 Javascript
小程序如何定位所在城市及发起周边搜索
2020/02/11 Javascript
JS实现烟花爆炸效果
2020/03/10 Javascript
Python标准模块--ContextManager上下文管理器的具体用法
2017/11/27 Python
pytorch permute维度转换方法
2018/12/14 Python
强悍的Python读取大文件的解决方案
2019/02/16 Python
python selenium自动化测试框架搭建的方法步骤
2020/06/14 Python
Python基于Serializer实现字段验证及序列化
2020/11/04 Python
HTML5 CSS3新的WEB标准和浏览器支持
2009/07/16 HTML / CSS
html5 canvas实现给图片添加平铺水印
2019/08/20 HTML / CSS
AmazeUI 等分网格的实现示例
2020/08/25 HTML / CSS
法国时尚童装网站:Melijoe
2016/08/10 全球购物
P/Invoke是什么
2015/07/31 面试题
教育实习生的自我评价分享
2013/11/21 职场文书
给小学生的新年寄语
2014/04/04 职场文书
根叔历年演讲稿
2014/05/20 职场文书
七年级上册语文教学计划
2015/01/22 职场文书
2015年乡镇卫生院妇幼保健工作总结
2015/05/19 职场文书
MYSQL主从数据库同步备份配置的方法
2021/05/26 MySQL
Java8利用Stream对列表进行去除重复的方法详解
2022/04/14 Java/Android
SQL语句多表联合查询的方法示例
2022/04/18 MySQL
Win10本地连接不见了怎么恢复? win10系统电脑本地连接不见了解决方法
2023/01/09 数码科技