LMLPHP后院

基于 HTML5 的 EventSource 实时推送实现技术

maybe yes 发表于 2017-08-21 18:03

本文介绍 Comet 的 EventSource 实现方式,EventSource 对象只是对数据格式进行了简单的封装。服务端加上 event-stream 的头声明数据以事件流的方式传递,保持长连接

先上代码吧,后端代码示例 chat.php

if (isset($_REQUEST['message'])) {
    file_put_contents('/tmp/message.txt',
        time() . '||data: ' . $_REQUEST['message'] . "\n", FILE_APPEND);
    echo $_REQUEST['message'];
    exit;
}

function output($v) {
    echo "data: {$v}\n\n";
    ob_flush();
    flush();
}

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header("Content-Encoding: none");
header('X-Accel-Buffering: no');
$last = time();

for (;;) {
    // exec('tail -n 1 /tmp/message.txt', $data);
    $tempArr = file('/tmp/message.txt');
    $arr = explode('||', end($tempArr));
    if ($arr[0] <= $last){
        sleep(1);
        continue;
    }
    $last = $arr[0];
    output($arr[1]);
    sleep(1);
}

一开始,读取文件最后一行内容使用 tail 命令导致程序运行一直不成功,实在是个坑。

前端代码实现 comet.php

<div id="result"></div>
<script>
if (typeof(EventSource)!=="undefined")
{
    var source=new EventSource("/chat.php");
    source.onmessage = function(event) {
        document.getElementById("result").innerHTML=event.data + "
";
    };
}else{
    document.getElementById("result").innerHTML="抱歉,您的浏览器不支持 server-sent 事件 ...";
}
</script>

本文示例后端使用文件保存聊天记录,读取文件内容更新返回给客户端,通过保持长连接和 chunked 传输实现实时通信。

经过长时间观察测试,EventSource 会每隔大约 5 分钟重新请求一次,稳定性不错,连续几天不下线都能保持连接。

相关文章
2024-04-19 09:55:17 1713491717 0.034503