如何确保PHP SSE不会断开"

时间:2017-12-13 18:46:51

标签: php server-sent-events

我在我的网站上运行了一个额外的聊天室服务,我使用SSE不断向客户端发送聊天更新,但是,由于断开连接和自动重新连接,似乎事件源的消息仍在触发或者至少是我在上网几个小时之后发现的。

这是我的PHP

header("Content-Type: text/event-stream");
header('Cache-Control: no-cache');

$matchid = $_GET["curMatch"];

$root = $_SERVER['DOCUMENT_ROOT'];
$filename = $root . "/pickup/chat/chatroom.txt";
$lastMod = NULL;

while(true){
    if(connection_status() != CONNECTION_NORMAL) {
        $conn->close();
        break;
    }

    clearstatcache();   

    $checker = filemtime($filename);
    if($checker != $lastMod){       
        $lastMod = $checker;
        echo "data: 1\n\n";
        ob_end_flush();
        flush();

        usleep(400);
    }   
}

这里是jQuery

matchID = 1;
if(typeof(EventSource) !== "undefined") {       
    var chatSource = new EventSource("/pickup/php/check-chat-sse.php?curMatch="+matchID);
    chatSource.onmessage = function(event) {
        var dt = new Date();
        var time = dt.getHours() + ":" + dt.getMinutes() + ":" + dt.getSeconds();
        console.log("Chat Server responded: @" +time);          
        console.log(event.data);            

        $.ajax({
            type: "POST",
            url: "/pickup/chat/"+matchID+".txt",
            datatype: 'text',
            success: function (response) {     
                $("#chat-content").html(response);
            }
        });
        if (hidden == true){
            $("#chat-toggle").addClass("newMessage");
        }
    }   
}

最后,控制台记录

  

聊天服务器响应:@ 20:36:54   聊天服务器响应:@ 20:37:24   聊天服务器响应:@ 20:38:52

这会导致每次服务器重新连接时都会添加.newMessage类,从而使用户认为在没有新消息时会有新消息。我在SSE上运行一个更复杂的系统也有同样的问题,所以如果我能得到解决方案,这一切都会更好。

因此,如何在不创建反向AJAX投票的情况下确保用户不会断开连接并重新连接,这是大多数人的建议。任何建议或帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

当客户端浏览器断开连接时,Apache进程将自动关闭php进程(我假设你正在使用Apache,因为你没有指定它)。因此,不需要while()循环的前四行,并且可能导致问题。 (但是,如果您确实保留它们,请开始记录connection_status()的返回值,以便了解它为何关闭连接。)

但是,由于您的重新连接每30秒发生一次,我的猜测是PHP脚本只是超时。尝试添加:

set_time_limit(0);

位于脚本的最顶层。 (或者,在while循环中放置set_time_limit(10)之类的东西是一种更复杂的方法,可以捕获真正的锁定代码。)

如果不是这样,我猜你需要发送一些保持活跃的消息。 (我的书,HTML5 SSE的数据推送应用程序,详细介绍了如何实现它。)

顺便说一句,您是否考虑过在SSE正文中发送实际的聊天消息,而不是只发送“有新数据”消息,然后要求客户端为他们做额外的请求?它应该更有效率。