热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PHP+SSE服务器向客户端推送消息[php入门]

SSE(server-sentevent)是基于HTML5的服务器推送消息事件,它允许服务端单向向浏览器客户端发送数据,SSE使用流信息向浏览器推送信息,浏览器自动接收服务端推送过

PHP+SSE服务器向客户端推送消息[linux入门]

SSE(server-sent event)是基于HTML5的服务器推送消息事件,它允许服务端单向向浏览器客户端发送数据,SSE使用流信息向浏览器推送信息,浏览器自动接收服务端推送过来的消息,它是基于HTTP协议。

SSE与WebSocket作用相似,都是建立浏览器与服务器之间的通信渠道,然后服务器向浏览器推送信息。 但是WebSocket比SSE强大很多,SSE只能作为一个轻量级的消息推送方案,解决了从服务端向客户端单向推送消息的场景,而Websocket是全双工通道,可以双向通信。 SSE应用场景可以是微博更新、股价更新、消息通知、赛事结果等。

目前主流浏览器都支持SSE,但是IE系除外。

客户端代码

先来看客户端代码,新建一个html页面文件,在script部分添加以下代码:

if(typeof(EventSource) !== "undefined") {
    let source = new EventSource("sse.php");
    source.Onmessage= (e) => {
        if (e.data == "null") {
            return false;
        } else {
            let edata = JSON.parse(e.data);
            $("#result").append(edata.id + ":" + edata.message + "
"
); } }; } else { alert("您的浏览器不支持SSE"); }

首先,使用typeof(EventSource)来判断浏览器对SSE的支持情况。

接着创建一个新的EventSource对象,然后定义发送更新的服务端的 URL(本例中是 "sse.php"),如果是跨域的请求,需要这样设置: let source = new EventSource("http://xxx.com/sse.php", { withCredentials: true });,并需要服务端代码开启允许跨域。

每接收到一次更新,就会发生 onmessage 事件。

当 onmessage 事件发生时,把已接收的数据推入 id 为 #result 的元素中。

EventSource 对象支持3种事件:

onopen:当通往服务器的连接被打开时触发。

onmessage:当接收到消息时触发。

onerror:当发生错误时触发。

出于安全,我们可以在onmessage事件中检测消息的来源域:

source.Onmessage= (e) => {
  if (e.origin != "https://www.helloweba.net") {
    alert("消息来源不属于https://www.helloweba.net");
    return;
  }
  ...
}

服务端代码

我们使用PHP来写一个服务端发送数据的例子,当然你也可以使用Java/Python等任意服务端语言实现。

服务器端事件流的语法是非常简单的。把 "Content-Type" 报头设置为 "text/event-stream"。现在,就可以开始发送事件流了。

header("X-Accel-Buffering: no");
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");
ob_end_clean();
ob_implicit_flush(1);

while(1){

    $data =  [
        "id" => time(),
        "message" => "欢迎来到helloweba,现在是北京时间".date("Y-m-d H:i:s")
    ];
    
    returnEventData($data);
    sleep(10);
}

function returnEventData($returnData, $event="message", $id=0, $retry=0){

    $str = "";
    if($id>0){
        $str .= "id: {$id}".PHP_EOL;
    }
    if($event){
        $str.= "event: {$event}".PHP_EOL;
    }
    if($retry>0){
        $str .= "retry: {$retry}".PHP_EOL;
    }
    if(is_array($returnData)){
        $returnData = json_encode($returnData);
    }
    $str .= "data: {$returnData}".PHP_EOL;
    $str .= PHP_EOL;
    echo $str;
}

以上代码流程大致为:

1.把报头 "Content-Type" 设置为 "text/event-stream"

2.规定不对页面进行缓存;

3.输出发送数据;

4.向客户端刷新输出数据。

注意:每一次发送的信息,由若干个message组成,每个message内部由若干行组成,每一行都是如下格式。

[field]: value

其中[field]有四个值,分别是:

id:数据标识符用id字段表示,相当于每一条数据的编号。

event:表示自定义的事件类型,默认是message事件。浏览器可以用addEventListener()监听该事件。

retry:指定浏览器重新发起连接的时间间隔。当时间间隔到期会重连,另外一个是由于网络错误等原因,导致连接出错时也会重连。

data:数据内容,如果数据很长,可以分成多行,最后一行用 结尾,前面行都用 结尾。

完整的消息内容格式:

id: msg1

event: foo

retry: 10000

data: some text

data: another message

data: with two lines 


上述代码中,我们设置了每隔10秒钟向客户端输出一条数据,实际应用中服务端有个任务当发现新的数据时就触发输出流事件。


推荐阅读
author-avatar
鹰击长空1943
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有