我开始使用 JavaScript EventSource 对象在 HTML5 中使用推送。我对 PHP 中的工作解决方案非常满意:
$time = 0;
while(true) {
if(connection_status() != CONNECTION_NORMAL) {
mysql_close()
break;
}
$result = mysql_query("SELECT `id` FROM `table` WHERE UNIX_TIMESTAMP(`lastUpdate`) > '".$time."'");
while($row = mysql_fetch_array($result)) {
echo "data:".$row["id"].PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
$time = time();
sleep(1);
}
但突然间我的 WebApp 无法访问,并出现 MySQL 错误“太多连接”。
原来在JavaScript中关闭事件源后MySQL连接没有关闭:
window.onload = function() {
sse = new EventSource("push.php");
sse.onmessage = function(event) {
console.log(event.data.split(":")[1]);
}
}
window.onbeforeunload = function() {
sse.close();
}
所以我猜测 PHP 脚本不会停止执行。有没有办法在客户端连接断开之前调用函数(如die();
)?为什么我的脚本在调用 EventSource 上的 .close();
后没有终止?!
感谢您的帮助! —
最佳答案
首先:当您将代码包装在一个巨大的while(true)
循环中时,您的脚本将永远不会终止。当您的脚本“用完要执行的代码”时,与数据库的连接将被关闭,但是由于您已经编写了死锁,所以这不会发生……永远。
这不是 EventSource
问题,它只是做了它应该做的事情。老实说,真的,可悲的是,这是你的错。
事情是这样的:用户连接到您的网站,EventSource
对象被实例化。建立与服务器的连接,并请求返回 push.php
的值。您的服务器按要求执行,并运行脚本,这 - 再一次 - 只不过是一个死锁。没有错误,所以它可以继续运行,只要 php.ini 允许它运行。 .close()
方法确实取消了输出流(或者更确切地说它应该),但是你的脚本太忙了,要么执行它的无限循环,要么休眠。假设脚本因为客户端断开连接而停止就像假设任何客户端都可能干扰服务器所做的事情一样。在安全方面,这将是可能发生的最坏情况。现在,回答您的实际问题:导致问题的原因是什么,如何解决?
答案:HEADERS
看this little PHP example : 脚本不会在服务器端保持事件状态(通过无限循环),而是通过设置正确的 header 。
作为旁注:请尽快放弃 mysql_*
,它正在被弃用(最终),使用 PDO
或 mysqli_*
代替。老实说,这并不难。
关于PHP 事件源继续执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12918650/