现在Web App中,大都有Ajax,是这样子:
HTML5有一个Server-Sent Events(SSE)功能,允许服务端推送数据到客户端。(通常叫数据推送)。基于数据推送是这样的,当数据源有新数据,它马上发送到客户端,不需要等待客户端请求。这些新数据可能是最新闻,最新股票行情,来自朋友的聊天信息,天气预报等。
数据拉与推的功能是一样的,用户拿到新数据。但数据推送有一些优势。 你可能听说过Comet, Ajax推送, 反向Ajax, HTTP流,WebSockets与SSE是不同的技术。可能最大的优势是低延迟。SSE用于web应用程序刷新数据,不需要用户做任何动作。
你可能听说过HTML5的WebSockets,也能推送数据到客户端。WebSockets是实现服务端更加复杂的技术,但它是真的全双工socket, 服务端能推送数据到客户端,客户端也能推送数据回服务端。SSE工作于存在HTTP/HTTPS协议,支持代理服务器与认证技术。SSE是文本协议你能轻易的调试它。如果你需要发送大部二进制数据从服务端到客户端,WebSocket是更好的选择。关于SSE与WebSocket的区别,本文下面会讲到。
HTML5 服务器发送事件(server-sent event)允许网页获得来自服务器的更新
Server-Sent 事件 - 单向消息传递
Server-Sent 事件指的是网页自动获取来自服务器的更新。
以前也可能做到这一点,前提是网页不得不询问是否有可用的更新。通过服务器发送事件,更新能够自动到达。
例子:Facebook/Twitter 更新、估价更新、新的博文、赛事结果等。
浏览器支持(所有主流浏览器均支持服务器发送事件,除了 Internet Explorer。)
EventSource 推送(ajax普通轮询):
处理过程:
客户端建立EventSource对象,对服务器通过http协议不断进行请求。服务器对客户端的响应数据格式有四部分构成,event,data,id,空格行。客户端接收到服务器端的响应数据之后,根据event事件值,找到EventSource对象对应的事件监听器。
接收 Server-Sent 事件通知
EventSource 对象用于接收服务器发送事件通知:
//创建一个新的 EventSource 对象,规定发送更新的页面的 URL var source = new EventSource("../api/MyAPI/ServerSentEvents"); //默认支持message事件 source.onmessage = function (event) { console.log(source.readyState); console.log(event); };
实例解析:
创建一个新的 EventSource 对象,然后规定发送更新的页面的 URL(本例中是 "demo_sse.php"),参数url就是服务器网址,必须与当前网页的网址在同一个网域(domain),而且协议和端口都必须相同。
每接收到一次更新,就会发生 onmessage 事件
检测 Server-Sent 事件支持
以下实例,我们编写了一段额外的代码来检测服务器发送事件的浏览器支持情况:
if(!!EventSource && typeof(EventSource)!=="undefined") { // 浏览器支持 Server-Sent // 一些代码.....}else{ // 浏览器不支持 Server-Sent..}
服务器端代码实例
为了让上面的例子可以运行,您还需要能够发送数据更新的服务器(比如 PHP、ASP、ASP.NET、Java)。
服务器端事件流的语法是非常简单的。你需要把 "Content-Type" 报头设置为 "text/event-stream"。现在,您可以开始发送事件流了。
我只会C#,所以用 ASP.NET的MVC 里面的ApiController写了个最简单的服务器端:
public class MyAPIController : ApiController { /// <summary> /// ...api/MyAPI/ServerSentEvents /// </summary> /// <returns></returns> [HttpGet, HttpPost] public Task<HttpResponseMessage> ServerSentEvents() { //Response.ContentType = "text/event-stream" //Response.Expires = -1 //Response.Write("data: " & now()) //Response.Flush() string data = "id: 123456\nevent: message\ndata: 666\n\n"; HttpResponseMessage response = new HttpResponseMessage { //注意:ContentType = "text/event-stream" Content = new StringContent(data, Encoding.GetEncoding("UTF-8"), "text/event-stream") }; return Task.FromResult(response); } }
代码解释:
把报头 "Content-Type" 设置为 "text/event-stream"
规定不对页面进行缓存
输出发送日期(始终以 "data: " 开头)
向网页刷新输出数据
EventSource 对象
新生成的EventSource实例对象,有一个readyState属性,表明连接所处的状态。
source.readyState
它可以取以下值:
0,相当于常量EventSource.CONNECTING,表示连接还未建立,或者连接断线。
1,相当于常量EventSource.OPEN,表示连接已经建立,可以接受数据。
2,相当于常量EventSource.CLOSED,表示连接已断,且不会重连。
在上面的例子中,我们使用 onmessage 事件来获取消息。不过还可以使用其他事件:
事件 描述
onopen 当通往服务器的连接被打开
onmessage 当接收到消息
onerror 当发生错误
open事件
连接一旦建立,就会触发open事件,可以定义相应的回调函数。
source.onopen = function(event) {
// handle open event
};
// 或者
source.addEventListener("open", function(event) {
// handle open event
}, false);
message事件
收到数据就会触发message事件。
source.onmessage = function(event) {
var data = event.data;
var origin = event.origin;
var lastEventId = event.lastEventId;
// handle message
};
// 或者
source.addEventListener("message", function(event) {
var data = event.data;
var origin = event.origin;
var lastEventId = event.lastEventId;
// handle message
}, false);
参数对象event有如下属性:
data:服务器端传回的数据(文本格式)。
origin: 服务器端URL的域名部分,即协议、域名和端口。
lastEventId:数据的编号,由服务器端发送。如果没有编号,这个属性为空。
error事件
如果发生通信错误(比如连接中断),就会触发error事件。
source.onerror = function(event) {
// handle error event
};
// 或者
source.addEventListener("error", function(event) {
// handle error event
}, false);
自定义事件
服务器可以与浏览器约定自定义事件。这种情况下,发送回来的数据不会触发message事件。
source.addEventListener("foo", function(event) {
var data = event.data;
var origin = event.origin;
var lastEventId = event.lastEventId;
// handle message
}, false);
上面代码表示,浏览器对foo事件进行监听。
close方法
close方法用于关闭连接。
source.close();
数据格式
概述
服务器端发送的数据的HTTP头信息如下:
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
后面的行都是如下格式:
field: value\n
field可以取四