mad*_*eye 7 php mysql connection ajax https
我有以下问题.
程序客户端向服务器发送HTTPS操作.服务器获取所需的操作和所有参数.但是,当被调用的PHP脚本工作时,客户端会断开连接.
脚本回应响应,客户端不会得到任何不应该的响应.因为它是重要的操作,客户端应该总是得到响应,我想在这种情况发生时阻止PHP脚本执行.
整个脚本都在MySQL事务中,因此如果它死了,则会发生数据库回滚,这是必不可少的.
我已将此代码放在脚本的最后
ob_end_clean();
header("Connection: close");
ignore_user_abort();
ob_start();
echo $response->asXML();
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();
if ( connection_aborted() )
log('Connection aborted');
else
log('Connection is fine');
Run Code Online (Sandbox Code Playgroud)
但是connection_aborted总是返回0(NORMAL CONNECTION),因此脚本总是执行.
connection_status
也没有帮助,所以我不知道还有什么可以尝试.
编辑:
我发现,只有在使用AJAX请求调用脚本时,这才会起作用.当使用常规HTTP调用它时,它表明连接已经死亡.但是,当我用new XMLHttpRequest()
它调用它时,从来没有想到连接已关闭.
它是异步请求.
所以我设法缩小了范围.但我仍然不知道如何解决它.
经过一些实验后,似乎您需要对连接进行多次刷新(写入)才能让 PHP 检测到连接已中止。然而,您似乎希望将输出写入一大块 XML 数据。我们可以通过使用 HTTP 请求的传输编码来解决没有更多数据可发送的问题chunked
。
ob_implicit_flush(true);
ignore_user_abort(true);
while (ob_get_level()) {
ob_end_clean();
}
header('Content-Type: text/xml; charset=utf-8');
header('Transfer-Encoding: chunked');
header('Connection: close');
// ----- Do your MySQL processing here. -----
// Sleep so there's some time to abort the connection. Obviously this wouldn't be
// here in production code, but is here to simulate time to process the request.
sleep(3);
// Put XML content into $xml. If output buffering is used, dump contents to $xml.
//$xml = $response->asXML();
$xml = '<?xml version="1.0"?><test/>';
$size = strlen($xml);
// If connection is aborted before here, connection_status() will not return 0.
echo dechex($size), "\r\n", $xml, "\r\n"; // Write content chunk.
echo "0\r\n\r\n"; // Write closing chunk, detecting if connection closed.
if (0 !== connection_status()) {
error_log('Connection aborted.');
// Rollback MySQL transaction.
} else {
error_log('Connection successful.');
// Commit MySQL transaction.
}
Run Code Online (Sandbox Code Playgroud)
ob_implicit_flush(true)
告诉 PHP 在每个语句后进行刷新echo
。每个块发送后都会检查连接状态echo
。如果连接在第一个语句之前关闭,connection_status()
则应返回非零值。
ini_set('zlib.output_compression', 0)
如果在 php.ini 中打开压缩,您可能需要在脚本顶部使用来关闭输出压缩,否则它充当另一个外部缓冲区并且connection_status()
可能始终返回0
.
编辑:Transfer-Encoding: chunked
标头修改浏览器期望在 HTTP 响应中接收数据的方式。然后,浏览器期望以块的形式接收数据[{Hexadecimal number of bytes in chunk}\r\n{data}\r\n]
。例如,您可以发送字符串“This is an example string”。通过 echo 作为一个块1a\r\nThis is an example string.\r\n
。浏览器只会显示字符串,而不是1a
,并保持连接打开,直到收到空块,即0\r\n\r\n
。
编辑:我修改了答案中的代码,以便它作为独立脚本工作,而不是依赖于$response
由OP的代码定义。也就是说,我对该行进行了注释$xml = $response->asXML();
并将其替换为$xml = '<?xml version="1.0"?><test/>';
作为概念证明。
仅当 PHP 尝试向浏览器发送某些输出时,它才能检测到连接已中止。尝试输出一些空白字符,flush()
输出,然后测试connection_status()
。您可能必须输出足够的字符才能让缓冲区通过,在我的例子中 64 kb 有效。
ob_end_flush();
flush();
sleep(10);
ignore_user_abort(true);
echo str_repeat(' ', 1024*64);
flush();
if ( connection_status() != 0 )
die();
Run Code Online (Sandbox Code Playgroud)
请注意,我添加了ignore_user_abort(true)
,如果没有它,执行将在脚本输出处结束,即在echo
或 处flush()
。
归档时间: |
|
查看次数: |
2091 次 |
最近记录: |