php定时计划任务与fsockopen持续进程实例


Posted in PHP onMay 23, 2014

Web服务器执行一个PHP脚本,有时耗时很长才能返回执行结果,后面的脚本需要等待很长一段时间才能继续执行。
如果想实现只简单触发耗时脚本的执行而不等待执行结果就直接执行下一步操作,可以通过fscokopen函数来实现。

PHP支持socket编程,fscokopen函数返回一个到远程主机连接的句柄,可以像使用fopen返回的句柄一样,对它进行 fwrite、fgets、fread等操作。
使用fsockopen连接到本地服务器,触发脚本执行,然后立即返回,不等待脚本执行完成,即可实现异步 执行PHP的效果。

例子:

<?  
function triggerRequest($url, $post_data = array(), $cookie = array()){  
  $method = "GET";  //通过POST或者GET传递一些参数给要触发的脚本  
  $url_array = parse_url($url); //获取URL信息  
  $port = isset($url_array['port'])? $url_array['port'] : 80;    
  $fp = fsockopen($url_array['host'], $port, $errno, $errstr, 30);  
  if (!$fp) {  
    return FALSE;  
  }  
  $getPath = $url_array['path'] ."?". $url_array['query'];  
  if(!empty($post_data)){  
    $method = "POST";  
  }  
  $header = $method . " " . $getPath;  
  $header .= " HTTP/1.1\r\n";  
  $header .= "Host: ". $url_array['host'] . "\r\n "; //HTTP 1.1 Host域不能省略  
  /*以下头信息域可以省略 
  $header .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13 \r\n"; 
  $header .= "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,q=0.5 \r\n"; 
  $header .= "Accept-Language: en-us,en;q=0.5 "; 
  $header .= "Accept-Encoding: gzip,deflate\r\n"; 
   */    $header .= "Connection:Close\r\n";  
  if(!empty($cookie)){  
    $_cookie = strval(NULL);  
    foreach($cookie as $k => $v){  
$_cookie .= $k."=".$v."; ";  
    }  
    $cookie_str =  "Cookie: " . base64_encode($_cookie) ." \r\n"; //传递Cookie  
    $header .= $cookie_str;  
  }  
  if(!empty($post_data)){  
    $_post = strval(NULL);  
    foreach($post_data as $k => $v){  
$_post .= $k."=".$v."&";  
    }  
    $post_str  = "Content-Type: application/x-www-form-urlencoded\r\n";   
    $post_str .= "Content-Length: ". strlen($_post) ." \r\n"; //POST数据的长度  
    $post_str .= $_post."\r\n\r\n "; //传递POST数据  
    $header .= $post_str;  
  }  
  fwrite($fp, $header);  
  //echo fread($fp, 1024); //服务器返回  
  fclose($fp);  
  return true;  
}  

这样就可以通过fsockopen()函数来触发一个PHP脚本的执行,然后函数就会返回。 接着执行下一步操作了。
现在存在一个问题:当客户端断开连接后,也就是triggerRequest发送请求后,立即关闭了连接,那么可能会引起服务器端正在执行的脚本退出

在 PHP 内部,系统维护着连接状态,其状态有三种可能的情况:

* 0 ? NORMAL(正常)
* 1 ? ABORTED(异常退出)
* 2 ? TIMEOUT(超时)

当 PHP 脚本正常地运行 NORMAL 状态时,连接为有效。当客户端中断连接时,ABORTED 状态的标记将会被打开。远程客户端连接的中断通常是由用户点击 STOP 按钮导致的。当连接时间超过 PHP 的时限(参阅 set_time_limit() 函数)时,TIMEOUT 状态的标记将被打开。

可以决定脚本是否需要在客户端中断连接时退出。有时候让脚本完整地运行会带来很多方便,即使没有远程浏览器接受脚本的输出。默认的情况是当远程客户端 连接 中断时脚本将会退出。该处理过程可由 php.ini 的 ignore_user_abort 或由 Apache .conf 设置中对应的"php_value ignore_user_abort"以及 ignore_user_abort() 函数来控制。如果没有告诉 PHP忽略用户的中断,脚本将会被中断,除非通过 register_shutdown_function() ,可以让我们设置一个当执行关闭时可以被调用的另一个函数.也就是说当我们的脚本执行完成或意外死掉导致PHP执行即将关闭时,我们的这个函数将会 被调用,当远程用户点击 STOP 按钮后,脚本再次尝试输出数据时,PHP 将会检测到连接已被中断,并调用关闭触发函数。

脚本也有可能被内置的脚本计时器中断。默认的超时限制为 30 秒。这个值可以通过设置 php.ini 的 max_execution_time 或 Apache .conf 设置中对应的"php_value max_execution_time"参数或者 set_time_limit() 函数来更改。当计数器超时的时候,脚本将会类似于以上连接中断的情况退出,先前被注册过的关闭触发函数也将在这时被执行。在该关闭触发函数中,可以通过调 用 connection_status() 函数来检查超时是否导致关闭触发函数被调用。如果超时导致了关闭触发函数的调用,该函数将返回 2。

注意,ABORTED 和 TIMEOUT 状态可以同时有效。这在告诉 PHP 忽略用户的退出操作时是可能的。PHP 将仍然注意用户已经中断了连接但脚本仍然在运行的情况。如果到了运行的时间限制,脚本将被退出,设置过的关闭触发函数也将被执行。在这时会发现函数 connection_status() 返回 3。

所以还在要触发的脚本中指明:

<?php  
ignore_user_abort(TRUE); //如果客户端断开连接,不会引起脚本abort  

set_time_limit(0); //取消脚本执行延时上限  
或使用: 
<?php  

register_shutdown_function(callback fuction[, parameters]); //注册脚本退出时执行的函数
PHP 相关文章推荐
php 将excel导入mysql
Nov 09 PHP
php函数之子字符串替换&amp;#65279; str_replace
Mar 23 PHP
php在页面中调用fckeditor编辑器的方法
Jun 10 PHP
php中判断数组是一维,二维,还是多维的解决方法
May 04 PHP
如何在PHP中使用正则表达式进行查找替换
Jun 13 PHP
解析thinkphp基本配置 convention.php
Jun 18 PHP
php中通过数组进行高效随机抽取指定条记录的算法
Sep 09 PHP
thinkPHP学习笔记之安装配置篇
Mar 05 PHP
PHP 双链表(SplDoublyLinkedList)简介和使用实例
May 12 PHP
了解PHP的返回引用和局部静态变量
Jun 04 PHP
关于php 高并发解决的一点思路
Apr 16 PHP
PHP中register_shutdown_function函数的基础介绍与用法详解
Nov 28 PHP
PHP+Mysql+Ajax+JS实现省市区三级联动
May 23 #PHP
PHP解析html类库simple_html_dom的转码bug
May 22 #PHP
浅谈discuz密码加密的方式
May 22 #PHP
PHP函数strip_tags的一个bug浅析
May 22 #PHP
PHP学习笔记之字符串编码的转换和判断
May 22 #PHP
PHP+memcache实现消息队列案例分享
May 21 #PHP
php+highchats生成动态统计图
May 21 #PHP
You might like
两个开源的Php输出Excel文件类
2010/02/08 PHP
PHP文件打开、关闭、写入的判断与执行代码
2011/05/24 PHP
php smarty 二级分类代码和模版循环例子
2011/06/01 PHP
php提示Call-time pass-by-reference has been deprecated in的解决方法[已测]
2012/05/06 PHP
PHP中防止直接访问或查看或下载config.php文件的方法
2012/07/07 PHP
php smtp实现发送邮件功能
2017/06/22 PHP
用ASP将SQL搜索出来的内容导出为TXT的代码
2007/07/27 Javascript
基于jquery的loading 加载提示效果实现代码
2011/09/01 Javascript
基于jquery &amp; json的省市区联动代码
2012/06/26 Javascript
jquery获取div距离窗口和父级dv的距离示例
2013/10/10 Javascript
JS深度拷贝Object Array实例分析
2016/03/31 Javascript
微信小程序 网络API 上传、下载详解
2016/11/09 Javascript
本地Bootstrap文件字体图标引入却无法显示问题的解决方法
2020/04/18 Javascript
vue中阻止click事件冒泡,防止触发另一个事件的方法
2018/02/08 Javascript
微信小程序实现左右联动的实战记录
2018/07/05 Javascript
vue-image-crop基于Vue的移动端图片裁剪组件示例
2018/08/28 Javascript
wx-charts 微信小程序图表插件的具体使用
2019/08/18 Javascript
详解Angular Karma测试的持续集成实践
2019/11/15 Javascript
原生js实现随机点餐效果
2019/12/10 Javascript
如何使用 JavaScript 操作浏览器历史记录 API
2020/11/24 Javascript
[37:23]DOTA2上海特级锦标赛主赛事日 - 3 胜者组第二轮#2Secret VS EG第二局
2016/03/04 DOTA
Python实现发送email的几种常用方法
2014/08/18 Python
python按照多个字符对字符串进行分割的方法
2015/03/17 Python
总结网络IO模型与select模型的Python实例讲解
2016/06/27 Python
Python基于回溯法子集树模板解决0-1背包问题实例
2017/09/02 Python
基于MTCNN/TensorFlow实现人脸检测
2018/05/24 Python
Python Selenium模块安装使用教程详解
2020/07/09 Python
详解CSS3原生支持div铺满浏览器的方法
2018/08/30 HTML / CSS
美国汽车交易网站:Edmunds
2016/08/17 全球购物
战友聚会主持词
2014/04/02 职场文书
八项规定对照检查材料
2014/08/31 职场文书
机关作风整顿个人整改措施思想汇报
2014/09/29 职场文书
招商引资工作汇报
2014/10/28 职场文书
家庭财产分割协议书范本
2014/11/24 职场文书
任命书标准格式
2015/03/02 职场文书
2015年统计员个人工作总结
2015/07/23 职场文书