javascript - SSE 非常慢

标签 javascript php html server-sent-events eventsource

目前正在写一个网页游戏的通信框架,通信图如下:代码如下:

测试.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/

相关文章:

javascript - 如何获得所有票价的总和

javascript - 同时选中两个复选框

html - 方形空间上的第 n 个类型

php - 如何从相同的多个数据库结果中选择一个结果

jquery - 如何使用 jQuery 从文件中添加内容?

javascript - 如何为文本区域设置值,并使用struts2操作获取它?

javascript - 如何知道所有子文件夹的名称

javascript - 扩展 JavaScript 的内置类型——它是邪恶的吗?

javascript - 在哪里以及如何在 PHP 文件中添加 JavaScript 代码和 CSS 代码?

php - ajax中常见的服务器响应页面原因?