测试.php:
<!DOCTYPE html>
<html>
<head>
<title> Test </title>
<script>
function init()
{
var source = new EventSource("massrelay.php");
source.onmessage = function(event)
{
console.log("massrelay sent: " + event.data);
var p = document.createElement("p");
var t = document.createTextNode(event.data);
p.appendChild(t);
document.getElementById("rec").appendChild(p);
};
}
function test()
{
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function ()
{
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200)
{
console.log("reciver responded: " + xhr.responseText);
}
}
xhr.open("GET", "reciver.php?d=" + document.getElementById("inp").value , true);
xhr.send();
console.log("you sent: " + document.getElementById("inp").value);
}
</script>
</head>
<body>
<button onclick="init()">Start Test</button>
<textarea id="inp"></textarea>
<button onclick="test()">click me</button>
<div id="rec"></div>
</body>
</html>
这需要用户输入(目前是一个用于测试的文本框)并将其发送到接收方,并将接收方的响应写回控制台,我从未收到过来自接收方的错误。它还为发送的 SSE 添加事件监听器。
reciver.php:
<?php
$data = $_REQUEST["d"];
(file_put_contents("data.txt", $data)) ? echo $data : echo "error writing";
?>
如您所见,这非常简单,仅用于将数据写入 data.txt,然后返回写入成功。 data.txt 只是传递给 massrelay.php 的“管”数据。
massrelay.php:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
while(1)
{
$data = file_get_contents("data.txt");
if ($data != "NULL")
{
echo "data: " . $data . "\n\n";
flush();
file_put_contents("data.txt", "NULL");
}
}
?>
massrelay.php 检查 data.txt 中是否有任何数据,如果有,将使用 SSE 将其传递给任何具有事件监听器的人,一旦读取数据,它将清除数据文件。
除了 massrelay.php 发送数据文件中的数据可能需要 30 秒到 10 分钟的轻微问题外,整个过程实际上运行良好。对于网页游戏来说,这是完全不能接受的,因为您需要实时操作。我想知道是否由于我的代码中的缺陷而花费了这么长时间,或者我是否正在考虑硬件(我自己将其托管在带有 sempron 的 2006 Dell 上)。如果有人发现它有任何问题,请告诉我,谢谢。
最佳答案
我发现您的代码存在三个问题:
- 不 sleep
- 没有 ob_flush
- session
您的 while() 循环不断读取文件系统。你需要放慢速度。我在下面睡了半秒钟;试验可接受延迟的最大值。
PHP 有自己的输出缓冲区。您使用 @ob_flush()
刷新它们(@
抑制错误)并使用 flush()
刷新 Apache 缓冲区。两者都需要,而且顺序也很重要。
最后,PHP session 锁定,因此如果您的客户端可能正在发送 session cookie,即使您的 SSE 脚本不使用 session 数据,您也必须在进入无限循环之前关闭 session 。
我已将所有这三项更改添加到您的代码中,如下所示。
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
session_write_close();
while(1)
{
$data = file_get_contents("data.txt");
if ($data != "NULL")
{
echo "data: " . $data . "\n\n";
@ob_flush();flush();
file_put_contents("data.txt", "NULL");
}
usleep(500000);
}
顺便说一句,另一个答案中关于使用内存数据库的建议很好,但文件系统开销以毫秒为单位,因此它无法解释“30 秒到 10 分钟”的延迟。
关于javascript - SSE 非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38676452/