PHP - 用户异常断开连接,脚本强制继续执行,异常退出回调
试想如下情况。如果你的用户正在执行一个需要非常长的执行时间的操作。他点了执行了之后,浏览器就开始蛋疼地转。如果执行5分钟,你猜他会干啥,显然会觉得什么狗屎垃圾站,这么久都不响应,然后就给关了。当然这个是一个极端的情况。但是我们不乏这种需求,需要用户关闭请求之后也能够做事情。脚本继续执行。再考虑另外一种情况。如果我们现在正在做一个非常精确的事情,用户一旦断开(异常或者是正常)之后必须要执行一些操作,比如他掉线了,我们需要把他的在线状态清空。
基于有这样的需求,我找到了 ignore_user_abort 这个函数。
当调用 ignore_user_abort(1) 时, 就设定了忽略用户退出这个标志位,也就是不管怎样,也要把程序执行到底,除非在程序中调用了 exit。(PHPINI也可以设置这个)
还有另一个函数函register_shutdown_function,它可以注册一个函数或方法,在程序退出的时候调用,有些类似于 javascript 里面的 onunload 和 onbeforeunload 事件。
ignore_user_abort(1)很简单,设置之后一直要直到你的脚本执行完成,当然这个也是一个非常危险的操作,可能会产生众多的僵尸进程,处理不当的话。
手册上如下描述:
注意: 以下内容对 PHP 3.0.7 及更高版本适用。
在 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() 设置了关闭触发函数。通过该关闭触发函数,当远程用户点击 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。
OK,看这个函数非常简单也很容易理解。注意上面一句话: register_shutdown_function() 设置了关闭触发函数。通过该关闭触发函数,当远程用户点击 STOP 按钮后,脚本再次尝试输出数据时,PHP 将会检测到连接已被中断,并调用关闭触发函数。
再去查一查 :register_shutdown_function() 如下描述:
Registers a callback to be executed after script execution finishes or exit() is called.
也就是说脚本执行完成的时候或者使用exit()的时候调用。
但是异常中断算什么。
再看加粗的那句话,当脚本尝试输出数据的时候PHP会检测到用户链接已经被中断,明白了,只要我输出就知道他是否中断,前几天看得flush函数又派上用场了,我只要一直flush就可以直到他中断没有。然后调用退出的回调函数。这个也是之前写的聊天状态管理为什么死循环里面写echo 1;flush();的原因。
PHP - 用户异常断开连接,脚本强制继续执行,异常退出回调的更多相关文章
- linux 服务器与客户端异常断开连接问题
服务器与客户端连接,客户端异常断掉之后服务器端口仍然被占用, 到最后是不是服务器端达到最大连接数就没法连接了?领导让我测试这种情况,我用自己的电脑当TCP Client,虚拟机当服务器,连接之后能正常 ...
- 在c#中利用keep-alive处理socket网络异常断开的方法
本文摘自 http://www.z6688.com/info/57987-1.htm 最近我负责一个IM项目的开发,服务端和客户端采用TCP协议连接.服务端采用C#开发,客户端采用Delphi开发.在 ...
- freeradius防止用户异常断开无法重新链接上
freeradius防止用户异常断开无法重新链接上 http://www.cnblogs.com/klobohyz/archive/2012/02/08/2342532.html 编辑default文 ...
- TCP连接异常断开检测(转)
TCP是一种面向连接的协议,连接的建立和断开需要通过收发相应的分节来实现.某些时候,由于网络的故障或是一方主机的突然崩溃而另一方无法检测到,以致始终保持着不存在的连接.下面介绍一种方法来检测这种异常断 ...
- (转)TCP连接异常断开检测
TCP是一种面向连接的协议,连接的建立和断开需要通过收发相应的分节来实现.某些时候,由于网络的故障或是一方主机的突然崩溃而另一方无法检测到,以致始终保持着不存在的连接.下面介绍一种方法来检测这种异常断 ...
- [转帖]linux screen 命令详解,xshell关掉窗口或者断开连接,查看断开前执行的命令
linux screen 命令详解,xshell关掉窗口或者断开连接,查看断开前执行的命令 https://binwaer.com/post/12.html yun install -y screen ...
- tcp 服务端如何判断客户端断开连接
一篇文章: 最近在做一个服务器端程序,C/S结构.功能方面比较简单就是client端与server端建立连接,然后发送消息给server.我在server端会使用专门的线程处理一条socket连接 ...
- 关于MySQL用户会话及连接线程
0.概念理解:用户会话和连接线程是什么关系? 用户会话和用户连接线程是一一对应的关系,一个会话就一个用户连接线程. 问题描述: 如果系统因为执行了一个非常大的dml或者ddl操作导致系统hang住,我 ...
- TCP建立连接和断开连接图解
参考博客: http://blog.csdn.net/whuslei/article/details/6667471 http://www.2cto.com/net/201310/251896.htm ...
随机推荐
- python学习-序列排序
python的排序中,可以使用内置的sort()来对序列进行排序,也可以使用内置的sorted()函数对序列进行排序,区别是,当使用sort()时,是对原序列进行排序,而sorted()则是生成一个新 ...
- ThinkPHP5 使用create 获取表单所有字段
TP5没有 TP3的那个create创建表单字段,如果字段太多,写起来是非常麻烦 只需要在 框架里面 think/db/Query.php 里面加上函数 public function create( ...
- 自定义vue全局组件use使用(解释vue.use()的原理)
我们在前面学习到是用别人的组件:Vue.use(VueRouter).Vue.use(Mint)等等.其实使用的这些都是全剧组件,这里我们就来讲解一下怎么样定义一个全局组件,并解释vue.use()的 ...
- Kanboard 看板工具配置使用
备注: 类似的开源工具有wekan 界面还有功能和Trello 类似.比较方便 1. 安装(基于docker+ docker-compose) a. 安装docker && ...
- (转)Maven的pom.xml文件结构之Build配置build
在Maven的pom.xml文件中,Build相关配置包含两个部分,一个是<build>,另一个是<reporting>,这里我们只介绍<build>. 1. 在M ...
- qt的webkit
qt4里面,在pro文件添加 QT += webkit qt5里面,在pro文件添加 QT += webkit webkitwidgets 备注: webkit不支持静态编译
- java 的一个hellow word 代码解释
/* This is a simple Java program. Call this file "Example.java". */(上面是注释的方法) class Exampl ...
- sys模块的问题,深浅COPY的应用场景,元祖与购物车程序练习-打印彩色\033[31;1m--------\033[0m
打印彩色:%s为变量,格式化 print("Added %s into shopping cart,your current balance is \033[31;1m%s\033[0m&q ...
- Windows2012使用笔记
一.介绍 win 2012的名字于北京时间2012年4月18日公布,全称Windows Server 2012(下面简称win 2012),正式版于2012年9月4日发布.这是一套基于Windows ...
- 使用GET方式提交的表单遇到的问题
经常使用表单,一直使用的都是POST方式,POST将数据封装到请求体中,相对于GET安全一点:而POST处理中文编码问题也比GET简单(GET需要将URL编码,后台接受到后还需要解码).今天我想要使用 ...