我从 W3 Schools 中获取了一个 SSE 示例,并注意到使用
Dev Tools
它不断创建新连接。查看 Kevin Choppin 的博客,我修改了 W3 Schools
示例以使用 while(true)
以及 ignore_user_abort()
和 connection_aborted()
。使用 Dev Tools
我现在可以看到一个持久连接,但是当我关闭选项卡或关闭浏览器时,我没有看到 `connection_aborted()' 返回 true。
上交所代码:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
ignore_user_abort(true);
while (true) {
if (connection_aborted()) {
file_put_contents("/tmp/test", "help");
exit();
}
$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
sleep(1);
}
?>
请注意,如果我将
file_put_contents()
移至 connection_aborted()
检查上方,则文件将成功写入。所以这不是权限问题。
我注意到有一个
connection_status()
功能。所以我修改了代码以使用 switch case 来显示状态。
上交所代码:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
ignore_user_abort(true);
while (true) {
switch (connection_status()) {
case CONNECTION_ABORTED:
file_put_contents("/tmp/test", "CONNECTION_ABORTED");
break;
case CONNECTION_NORMAL:
file_put_contents("/tmp/test", "CONNECTION_NORMAL");
break;
case CONNECTION_TIMEOUT:
file_put_contents("/tmp/test", "CONNECTION_TIMEOUT");
break;
case __COMPILER_HALT_OFFSET__:
file_put_contents("/tmp/test", "__COMPILER_HALT_OFFSET__");
break;
default:
break;
}
$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
sleep(1);
}
?>
使用此代码,文件会不断被写入,并且我收到
CONNECTION_NORMAL
作为我的输出。
ls -l /tmp/test ; cat /tmp/test
-rw-r--r-- 1 <user> <user> 17 Jan 18 11:09 /tmp/test
CONNECTION_NORMAL
连接没有中止,我很难找出原因。我在浏览器中使用
Microsoft Edge
,但也尝试了 Chrome
和 Firefox
。我还完全关闭了浏览器并使用 Task Manager
来终止该进程。已经过去 20 分钟了,时间戳仍在更新 CONNECTION_NORMAL
。
至于在浏览器中运行的客户端代码,与
W3 Schools
示例相同。
<!DOCTYPE html>
<html>
<body>
<h1>Getting server updates</h1>
<div id="result"></div>
<script>
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("demo_sse.php");
source.onmessage = function(event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
</body>
</html>
关于后端,服务器正在运行
apache
。
看到@JS_Riddler 的这个答案后获得更多信息。我对此的理解是,如果输出被缓冲,即使使用flush(),PHP也可能不会中止连接。我添加了带有
ob_get_contents()
和 ob_end_clean()
的 while 循环,但没有成功。此外,我还复制了 DestructTester
类的确切示例,无论 ignore_user_abort()
是否设置为 true
,输出都是相同的。每张照片都是NO
。
上交所代码:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
ignore_user_abort(true);
while (true) {
switch (connection_status()) {
case CONNECTION_ABORTED:
file_put_contents("/tmp/test", "CONNECTION_ABORTED");
break;
case CONNECTION_NORMAL:
file_put_contents("/tmp/test", "CONNECTION_NORMAL");
break;
case CONNECTION_TIMEOUT:
file_put_contents("/tmp/test", "CONNECTION_TIMEOUT");
break;
case __COMPILER_HALT_OFFSET__:
file_put_contents("/tmp/test", "__COMPILER_HALT_OFFSET__");
break;
default:
break;
}
$time = date('r');
echo "data: The server time is: {$time}\n\n";
while (ob_get_level()){
ob_get_contents();
ob_end_clean();
}
flush();
sleep(1);
}
?>
另一个更新。如果在客户端我使用
source.close();
它仍然没有检测到连接中止。我还尝试将 output_buffering
中的 php.ini
设置为 0,但没有成功。这感觉很破碎。