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.stayed.cn\') { alert(\'消息来源不属于https://www.stayed.cn\'); 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" => \'欢迎来到stayed,现在是北京时间\'.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\\n
其中[field]
有四个值,分别是:
id
:数据标识符用id字段表示,相当于每一条数据的编号。
event
:表示自定义的事件类型,默认是message
事件。浏览器可以用addEventListener()
监听该事件。
retry
:指定浏览器重新发起连接的时间间隔。当时间间隔到期会重连,另外一个是由于网络错误等原因,导致连接出错时也会重连。
data
:数据内容,如果数据很长,可以分成多行,最后一行用\\n\\n
结尾,前面行都用\\n
结尾。
完整的消息内容格式:
id: msg1\\n event: foo\\n retry: 10000\\n data: some text\\n data: another message\\n data: with two lines \\n\\n
上述代码中,我们设置了每隔10秒钟向客户端输出一条数据,实际应用中服务端有个任务当发现新的数据时就触发输出流事件。
本文地址:https://www.stayed.cn/item/126
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我