登录 ×

梨花寨前端技术交流平台!

html,css,js,html5,css3等

HTML5 服务器发送事件(server-sent event)

2018-07-20 10:47:11 | 浏览量:64 前沿信息

    HTML5 服务器发送事件(server-sent event)允许网页获得来自服务器的更新。用于网页自动获取服务器上更新的数据,它是一个实时性的机制,单向消息传递。

实时性获取数据的解决方案

对于某些需要实时更新的数据(例如 股价更新、新的博文、赛事结果等)来说,有这么几种解决方案:

Polling(轮询)

    在客户端重复的向服务端发送新请求。如果服务器没有新的数据更动,关闭本次连接。然后客户端在稍等一段时间之后,再次发起新请求,一直重复这样的步骤。

Long-polling(长轮询)

    在长轮询中,客户端发送一个请求到服务端。如果服务端没有新的数据变动,那么本次连接将会被保持,直到等待到更新后的数据,返回给客户端并关闭这个连接。

Server-Sent Events

    SSE类似于长轮询的机制,但是它在每一次的连接中,不只等待一次数据的更动。客户端发送一个请求到服务端 ,服务端保持这个请求直到一个新的消息准备好,将消息返回至客户端,此时不关闭连接,仍然保持它,供其它消息使用。SSE的一大特色就是重复利用一个连接来处理每一个消息(又称event)。

WebSocket

    WebSocket不同于以上的这些技术,因为它提供了一个真正意义上的双向连接。WebSocket是HTML5中非常强大的新特性,已经得到广泛应用。

WebSocket与Server-Sent Events 区别:

    WebSockets是实现服务端更加复杂的技术,但它是真的全双工通道,可以双向通信。服务端能推送数据到客户端,客户端也能推送数据回服务端。

如果你需要发送大部二进制数据从服务端到客户端,WebSocket是更好的选择。WebSocket是一个新的协议,需要额外部署。

    Server-Sent Events是一个轻量级协议,相对简单;SSE是文本协议你能轻易的调试它。SSE是单向通道,只能服务器向浏览器端发送。SSE默认支持断线重连,SSE支持自定义发送的数据类型。

SSE工作于存在HTTP/HTTPS协议,支持代理服务器与认证技术。SSSE则是部署在HTTP协议之上的,现有的服务器软件都支持。

这里主要讲解Server-Sent Events。

实现过程:

    客户端建立EventSource对象,对服务器通过http协议不断进行请求。服务器对客户端的响应数据格式有四部分构成,event,data,id,空格行。客户端接收到服务器端的响应数据之后,根据event事件值,找到EventSource对象对应的事件监听器。

一个基本例子——动态更新时间:

在html页面中显示一个动态变化的时间,这里使用Server-Sent Events来实现,在后台获取时间,不断发送给前台。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>HTML5 服务器发送事件(Server-Sent Events)-单向消息传递</title>
</head>
<body>
    <h1>获取服务端更新数据</h1>
    <div id="result"></div>
<script>
if(typeof(EventSource)!=="undefined")
{
    var source = new EventSource("/api/demo_sse.php");
    //默认支持open事件,当通往服务器的连接被打开时触发事件
    source.onopen = function (event) {
        console.log(source.readyState);
        console.log(event);
    };
    //默认支持error事件
    source.onerror = function (event) {
        console.log(source.readyState);
        console.log(event);
    };
    //默认支持message事件
    source.onmessage = function (event) {
        console.log(source.readyState);
        console.log(event);
        document.getElementById("result").innerHTML += event.data + "<br>";
    };

    //处理服务器响应报文中的自定义事件
    source.addEventListener("CustomEvent", function (e) {
        console.log("唤醒自定义事件");
        console.log(e);
        document.getElementById("result").innerHTML += e.data + "<br>";
    });
}
else{
    document.getElementById("result").innerHTML="抱歉,你的浏览器不支持server-sent事件...";
}
</script>
</body>
</html>

实例解析:

    创建一个新的EventSource对象,然后规定发送更新的页面的URL(本例中是"demo_sse.php")参数url就是服务器网址,必须与当前网页的网址在同一个网域(domain),而且协议和端口都必须相同。

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

当onmessage事件发生时,得到服务端传递的数据,把已接收的数据推入id为"result"的元素中。

close方法用于关闭连接:source.close();

服务器端代码实例:

PHP 代码(demo_sse.php):

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
?>

服务器端事件流的语法是非常简单的。

1、把"Content-Type"报头设置为"text/event-stream"。现在,可以开始发送事件流了。

2、规定不对页面进行缓存,header('Cache-Control: no-cache');

3、输出发送日期(始终以"data: "开头),注意一定要有两个\n\n作为结尾

4、向网页刷新输出数据,flush();

    运行页面效果是页面每3秒钟显示1次服务器时间,这一过程,具体是如何实现的?

    对于demo_sse.php来说,每次相应客户端的请求,服务端只会输出1次系统当前时间,使用flush()方法清空输出缓冲区,本次HTTP会话立刻结束。那页面为何会显示出一连串的时间戳呢?通过抓包可以看到,客户端(浏览器),每3秒钟向demo_sse.php发出一次GET请求,且每次请求都一模一样。

需求及问题提交:

点击图片更换数字

0.6565s