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作的文本留言本的例子(一)
Oct 09 PHP
透析PHP的配置文件php.ini
Oct 09 PHP
简单采集了yahoo的一些数据
Feb 14 PHP
在PHP中养成7个面向对象的好习惯
Jul 17 PHP
php 定义404页面的实现代码
Nov 19 PHP
dedecms中使用php语句指南
Nov 13 PHP
Yii框架form表单用法实例
Dec 04 PHP
PHP5多态性与动态绑定介绍
Apr 03 PHP
PHP实现二叉树的深度优先与广度优先遍历方法
Sep 28 PHP
php用正则判断是否为数字的方法
Mar 25 PHP
PHP面向对象之工作单元(实例讲解)
Jun 26 PHP
Thinkphp 框架基础之源码获取、环境要求与目录结构分析
Apr 27 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的ob_start来生成静态页面的方法分析
2011/03/09 PHP
php  单例模式详细介绍及实现源码
2016/11/05 PHP
PHP Header失效的原因分析及解决方法
2016/11/16 PHP
JavaScript分析、压缩工具JavaScript Analyser
2014/12/31 Javascript
js查看一个函数的执行时间实例代码
2015/09/12 Javascript
获取input标签的所有属性的方法
2016/06/28 Javascript
微信小程序 for 循环详解
2016/10/09 Javascript
快速解决js中window.location.href不工作的问题
2016/11/02 Javascript
jQuery基本筛选选择器实例代码
2017/02/06 Javascript
Vue插件写、用详解(附demo)
2017/03/20 Javascript
JS排序之选择排序详解
2017/04/08 Javascript
AngularJS2 与 D3.js集成实现自定义可视化的方法
2017/12/01 Javascript
vue.js实现插入数值与表达式的方法分析
2018/07/06 Javascript
JS栈stack类的实现与使用方法示例
2019/01/31 Javascript
node.js爬虫框架node-crawler初体验
2020/10/29 Javascript
Python的SQLAlchemy框架使用入门
2015/04/29 Python
浅谈Python 集合(set)类型的操作——并交差
2016/06/30 Python
Python中遇到的小问题及解决方法汇总
2017/01/11 Python
详谈Python基础之内置函数和递归
2017/06/21 Python
Python爬虫设置代理IP的方法(爬虫技巧)
2018/03/04 Python
Python中GeoJson和bokeh-1的使用讲解
2019/01/03 Python
Python3.5内置模块之os模块、sys模块、shutil模块用法实例分析
2019/04/27 Python
Python3运算符常见用法分析
2020/02/14 Python
mac系统下安装pycharm、永久激活、中文汉化详细教程
2020/11/24 Python
用python对excel进行操作(读,写,修改)
2020/12/25 Python
CSS3中的content属性使用示例
2015/07/20 HTML / CSS
html5标记文字_动力节点Java学院整理
2017/07/11 HTML / CSS
UNIX特点都有哪些
2016/04/05 面试题
教师个人自我鉴定
2014/02/08 职场文书
公司门卫岗位职责
2014/03/15 职场文书
新年爱情寄语
2014/04/08 职场文书
2014年计划生育协会工作总结
2014/11/14 职场文书
安装工程师岗位职责
2015/02/13 职场文书
罗马假日观后感
2015/06/08 职场文书
vue中三级导航的菜单权限控制
2021/03/31 Vue.js