2024年波兰PHPC

连接处理

在PHP内部,保持连接状态。有4个可能的状态:

  • 0-正常
  • 1-流产
  • 2-超时
  • 3-中止和超时

当PHP脚本正常运行时,NORMAL状态处于活动状态。如果远程客户端断开连接,则ABORTED状态标志为打开。远程客户端断开连接通常是由于用户点击停止按钮。如果PHP规定的时间限制(参见设置时间限制())命中时,TIMEOUT状态标志已启用。

您可以决定是否希望客户端断开连接导致您的脚本将被中止。有时,总是有你的即使没有远程浏览器接收,脚本也会一直运行到完成输出。然而,脚本的默认行为是当远程客户端断开连接时中止。这种行为可能是通过ignoreuserabort设置php.ini公司指令以及通过相应的php值忽略用户中止阿帕奇httpd.conf网址指令或使用ignore_user_abort()功能。如果你这么做不要告诉PHP忽略用户中止和用户中止,您的脚本将终止。唯一的例外是如果您注册了关机函数使用寄存器关闭函数()。使用关闭功能,当远程用户点击STOP按钮时下次脚本尝试输出PHP将检测到的内容时连接已中止,并调用了关闭函数。此关闭函数也将在脚本末尾被调用正常终止,以便在客户端的情况下做一些不同的事情断开连接,您可以使用connection_aborted()功能。此函数将返回真的如果连接是已中止。

您的脚本也可以由内置脚本计时器终止。默认超时为30秒。可以使用更改这个最大执行时间 php.ini公司指令或相应的php_value最大执行时间阿帕奇httpd.conf网址指令以及这个设置时间限制()功能。当计时器过期时,脚本将被中止,与上述客户端一样断开连接,如果已注册关闭功能,它将被调用。在此关闭功能中,您可以检查超时导致通过调用连接状态()功能。此功能将如果超时导致调用关闭函数,则返回2。

需要注意的一点是ABORTED和TIMEOUT状态可以同时激活。如果你告诉我,这是可能的PHP忽略用户中止。PHP仍然会注意到以下事实用户可能断开了连接,但脚本将保留正在运行。如果达到时间限制,它将被中止并您的关闭函数(如果有)将被调用。此时此刻你会发现的连接状态()返回3。

添加注释

用户贡献的笔记12条注释

gmail dot com的tom lgold2003
14年前
嘿,多亏了arr1,当我需要快速返回用户然后做其他事情时,它对我非常有用。

当使用这些代码时,我几乎要发疯了,我发现了另一件可能影响代码的事情:

内容编码:gzip

这是因为zlib已打开,内容将被压缩。但在所有输出结束之前,这不会输出缓冲区。

因此,它可能需要发送标头以防止出现此问题。

现在,代码变为:

<?php(电话)
对象结束清理
();
收割台(“连接:关闭\r\n”);
收割台(“内容编码:无\r\n”);
忽略用户中止(真的);//可选
对象启动(_S)();
回声(
'用户将看到的文本');
$大小=对象获取长度();
收割台(“内容长度:$大小");
对象结束刷新();//奇怪的行为,行不通
脸红();//除非两者都被调用!
开始清理();

//在此处进行处理
睡觉(5);

回声(
'文本用户永远看不到');
//做一些处理
?>
英国hotmail dot公司arr1
17年前
自4.1以来,在保持php脚本运行的同时关闭用户浏览器连接一直是一个问题,当时register_shutdown_function()的行为被修改为不会自动关闭用户连接。

sts在mail dot xubion dot hu
发布了原始解决方案:

<?php(电话)
收割台
(“连接:关闭”);
对象启动(_S)();
phpinfo公司();
$大小=对象获取长度();
收割台(“内容长度:$大小");
对象结束刷新();
脸红();
睡觉(13);
错误日志(“在幕后做点什么”);
?>

在将phpinfo()替换为
echo('我希望用户看到的文本');在这种情况下,永远不会发送标题!

解决方案是在发送头信息之前显式关闭输出缓冲并清除缓冲区。

例子:

<?php(电话)
对象结束清理
();
收割台(“连接:关闭”);
忽略用户中止();//可选的
对象启动(_S)();
回声(
'用户将看到的文本');
$大小=对象获取长度();
收割台(“内容长度:$大小");
对象结束刷新();//奇怪的行为,行不通
脸红();//除非两者都被调用!
//在此处进行处理
睡觉(30);
回声(
'文本用户永远看不到');
?>

刚刚花了3个小时想弄明白这一点,希望它能帮助别人:)

测试地点:
IE 7.5730.11标准
Mozilla Firefox 1.81
19年前
最后一条评论中提到的观点并不总是如此。

如果用户的连接在订单处理脚本确认用户信用卡/将其添加到数据库等过程中中途丢失(由于他们的ISP停机、网络故障……等等),并且您的脚本尝试发回输出(例如“预处理订单”或任何其他类型的确认),然后脚本将中止,这可能会导致进程出现问题。

我有一个订单脚本,它将数据添加到InnoDB数据库(通过MySQL),并且只在成功完成后提交事务。如果没有ignore_user_abort(),我曾经遇到过用户的连接在处理阶段断开的情况。。。他们的卡被收费了,但他们没有被添加到我的本地数据库中。

因此,如果您正在处理应该继续进行的敏感事务,无论用户是否在另一端“观看”,都可以安全地忽略任何中止。
mhumann在comciencia dot cl
10年前
我在重定向到工作时遇到了很多问题,之后我的脚本打算在后台继续工作。重定向到我的站点的另一个页面只会在原始页面完成处理后生效。

我终于发现了问题所在:
只有在脚本的末尾,PHP才会关闭会话,因为对会话数据的访问被锁定,以防止多个页面同时写入会话,所以在原始处理完成之前,无法加载新页面。

解决方案:
使用session_write_Close()重定向时手动关闭会话:

<?php(电话)
忽略用户中止
(真的);
设置时间限制(0);

$strURL=“在此处输入您的修正”
收割台(“位置:$strURL",真的);
收割台(“连接:关闭”,真的);
收割台(“内容编码:无\r\n”);
收割台(“内容长度:0”,真的);

脸红();
对象刷新(_F)();

session_write_close(会话写入关闭)();

//继续处理。。。

睡觉(100);
出口;
?>

但要小心:
确保脚本不会在session_write_close()之后(即在后台处理代码中)写入会话。这行不通。还要避免阅读,记住,下一个脚本可能已经修改了数据。

因此,在重定向之前,请尝试读取所需的数据。
gmail网站a1n2ton
14年前
PHP在连接中止时更改目录,因此这样的代码不会执行您想要的操作:

<?php(电话)
功能中止()
{
如果(
连接已中止())
取消链接('文件.ini');
}
寄存器关闭功能('中止');
?>

实际上,它会删除apaches根目录中的文件,所以如果您想在中止或写入时取消脚本目录中的文件链接,则必须存储目录
<?php(电话)
功能中止()
{
全球的
$dsd(美元)
如果(
连接已中止())
取消链接($dsd(美元).'/file.ini');
}
寄存器关闭函数('中止');
$dsd(美元)=获取cwd();
?>
马尔科
7年前
由于某些原因,此处未列出CONNECTION_XXX常量:

0=连接正常
1=连接已中断
2=连接超时
3=CONNECTION_ABORTED和CONNECTION_TIMEOUT

第三项是这样有效测试的:
if(CONNECTION_ABORTED&CONNECTION_TIMEOUT)
echo'连接已中止且超时';
伊利亚·彭亚耶夫
11年前
当我试图让脚本将客户端重定向到另一个URL,然后继续处理时,我陷入了困境。原因是php-fpm。所有可能的缓冲区刷新都不起作用,除非我调用了fastcgi_finish_request();

例如:

<?php(电话)
//正在重定向。。。
忽略用户中止(真的);
收割台(“位置:”.$redirectUrl,真的);
收割台(“连接:关闭”,真的);
收割台(“内容长度:0”,真的);
对象结束刷新();
脸红();
fastcgi完成请求();//使用php-fpm时很重要!

睡觉(5);//用户不会感觉到这种睡眠,因为他已经离开了

//在重定向用户后执行一些操作
?>
匿名
16年前
关于过账:
英国hotmail dot公司arr1

如果您使用/写入会话,则需要先执行以下操作:
(否则不起作用)

session_write_close();

如果需要:

ignore_user_abort(真);
而不是ignore_user_abort();
mail dot com上的pulstar
20年前
这些功能非常有用,例如,如果您需要控制网站中的访问者何时下单,并且您需要检查他/她是否没有单击提交按钮两次或在单击提交按钮后取消提交。
如果访问者在提交后单击停止按钮,脚本可能会在注册产品的过程中停止,并且没有完成列表,从而在数据库中产生不一致。
使用ignore_user_abort()函数,您可以让脚本完成所有工作,然后可以使用register_shutdown_function()和connection_aborted()检查访问者是否取消了提交或失去了连接。如果他/她这样做了,您可以将订单设置为未确认,当访客回来时,您可以再次提交旧订单。
为了防止双击提交按钮,可以使用javascript禁用它,也可以在脚本中为该顺序设置一个标志,该标志将被记录到数据库中。在接受新提交之前,脚本将检查之前是否没有下过相同的订单并拒绝它。这很好,因为脚本以前已经完成了作业。
请注意,如果在脚本的开头使用ob_start(“callback_function”),则可以指定一个回调函数,该函数在脚本结束时类似于shutdown函数,也可以让您在将生成的页面发送给访问者之前对其进行处理。
匿名
12年前
这个简单的函数输出一个字符串并关闭连接。它使用“ob_zhandler”考虑压缩

我花了一点时间才把这些放在一起,主要是因为将编码设置为“无”,正如一些人在这里指出的那样,不起作用。

<?php(电话)
功能输出字符串和关闭连接2($字符串到输出)
{
设置时间限制(0);
忽略用户中止(真的);
//缓冲所有即将到来的输出-确保我们关心压缩:
如果(!对象启动(_S)(“ob_zhhandler”))
对象启动(_S)();
回声
$字符串到输出
//获取输出的大小
$大小=对象获取长度();
//发送标题以通知浏览器关闭连接
收割台(“内容长度:$大小");
收割台('连接:关闭');
//冲洗所有输出
对象结束刷新();
对象刷新(_F)();
脸红();
//关闭当前会话
如果(会话id())session_write_close(会话写入关闭)();
}
?>
让·查尔斯·马马纳
16年前
connection_status()仅当客户端正常断开连接(使用STOP按钮)时才返回ABORTED状态。在这种情况下,浏览器发送RST TCP数据包,通知PHP连接已关闭。
但是。。。。如果连接因网络故障而停止(例如wifi链接断开),则脚本不知道客户端已断开连接:(

我尝试过使用fopen(“php://输出“)在写入时使用stream_select()来检测写入锁定(由于缓冲区已满),但php给了我这个错误:”不能将Output类型的流表示为可选择的()描述符“

所以我不知道如何正确检测网络连接故障。。。
罗伯特在go dot rw
8年前
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
/*
*反模式
*/

#连接
mysql_connect('localhost','username','password')或die('Could not connect:'.mysql_error());

#选择数据库
mysql_select_db('someDatabase')或die('Could not select database');

#执行数据库查询
$query=“从someTable中选择*”;
$result=mysql_query($query)或die('查询失败:'.mysql_error());

#过滤行并回显所需信息
while($row=mysql_fetch_object($result)){
echo$row->名称;
}
到顶部