原文来自于:http://javascript.ruanyifeng.com/htmlapi/eventsource.html

目录

概述

传统的网页都是浏览器向服务器“查询”数据,但是很多场合,最有效的方式是服务器向浏览器“发送”数据。比如,每当收到新的电子邮件,服务器就向浏览器发送一个“通知”,这要比浏览器按时向服务器查询(polling)更有效率。

服务器发送事件(Server-Sent Events,简称SSE)就是为了解决这个问题,而提出的一种新API,部署在EventSource对象上。目前,除了IE,其他主流浏览器都支持。

简单说,所谓SSE,就是浏览器向服务器发送一个HTTP请求,然后服务器不断单向地向浏览器推送“信息”(message)。这种信息在格式上很简单,就是“信息”加上前缀“data: ”,然后以“\n\n”结尾。

$ curl http://example.com/dates
data: 1394572346452 data: 1394572347457 data: 1394572348463 ^C

SSE与WebSocket有相似功能,都是用来建立浏览器与服务器之间的通信渠道。两者的区别在于:

  • WebSocket是全双工通道,可以双向通信,功能更强;SSE是单向通道,只能服务器向浏览器端发送。

  • WebSocket是一个新的协议,需要服务器端支持;SSE则是部署在HTTP协议之上的,现有的服务器软件都支持。

  • SSE是一个轻量级协议,相对简单;WebSocket是一种较重的协议,相对复杂。

  • SSE默认支持断线重连,WebSocket则需要额外部署。

  • SSE支持自定义发送的数据类型。

从上面的比较可以看出,两者各有特点,适合不同的场合。

客户端代码

概述

首先,使用下面的代码,检测浏览器是否支持SSE。

if (!!window.EventSource) {
// ...
}

然后,部署SSE大概如下。

var source = new EventSource('/dates');

source.onmessage = function(e){
console.log(e.data);
}; // 或者 source.addEventListener('message', function(e){})

建立连接

首先,浏览器向服务器发起连接,生成一个EventSource的实例对象。

var source = new EventSource(url);

参数url就是服务器网址,必须与当前网页的网址在同一个网域(domain),而且协议和端口都必须相同。

下面是一个建立连接的实例。

if (!!window.EventSource) {
var source = new EventSource('http://127.0.0.1/sses/');
}

新生成的EventSource实例对象,有一个readyState属性,表明连接所处的状态。

source.readyState

它可以取以下值:

  • 0,相当于常量EventSource.CONNECTING,表示连接还未建立,或者连接断线。

  • 1,相当于常量EventSource.OPEN,表示连接已经建立,可以接受数据。

  • 2,相当于常量EventSource.CLOSED,表示连接已断,且不会重连。

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可以取四个值:“data”, “event”, “id”, or “retry”,也就是说有四类头信息。每次HTTP通信可以包含这四类头信息中的一类或多类。\n代表换行符。

以冒号开头的行,表示注释。通常,服务器每隔一段时间就会向浏览器发送一个注释,保持连接不中断。

: This is a comment

下面是一些例子。

: this is a test stream\n\n

data: some text\n\n

data: another message\n
data: with two lines \n\n

data:数据栏

数据内容用data表示,可以占用一行或多行。如果数据只有一行,则像下面这样,以“\n\n”结尾。

data:  message\n\n

如果数据有多行,则最后一行用“\n\n”结尾,前面行都用“\n”结尾。

data: begin message\n
data: continue message\n\n

总之,最后一行的data,结尾要用两个换行符号,表示数据结束。

以发送JSON格式的数据为例。

data: {\n
data: "foo": "bar",\n
data: "baz", 555\n
data: }\n\n

id:数据标识符

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

id: msg1\n
data: message\n\n

浏览器用lastEventId属性读取这个值。一旦连接断线,浏览器会发送一个HTTP头,里面包含一个特殊的“Last-Event-ID”头信息,将这个值发送回来,用来帮助服务器端重建连接。因此,这个头信息可以被视为一种同步机制。

event栏:自定义信息类型

event头信息表示自定义的数据类型,或者说数据的名字。

event: foo\n
data: a foo event\n\n data: an unnamed event\n\n event: bar\n
data: a bar event\n\n

上面的代码创造了三条信息。第一条是foo,触发浏览器端的foo事件;第二条未取名,表示默认类型,触发浏览器端的message事件;第三条是bar,触发浏览器端的bar事件。

retry:最大间隔时间

浏览器默认的是,如果服务器端三秒内没有发送任何信息,则开始重连。服务器端可以用retry头信息,指定通信的最大间隔时间。

retry: 10000\n

服务器代码

服务器端发送事件,要求服务器与浏览器保持连接。对于不同的服务器软件来说,所消耗的资源是不一样的。Apache服务器,每个连接就是一个线程,如果要维持大量连接,势必要消耗大量资源。Node.js则是所有连接都使用同一个线程,因此消耗的资源会小得多,但是这要求每个连接不能包含很耗时的操作,比如磁盘的IO读写。

下面是Node.js的服务器发送事件的代码实例

var http = require("http");

http.createServer(function (req, res) {

    var fileName = "." + req.url;

    if (fileName === "./stream") {
res.writeHead(200, {"Content-Type":"text/event-stream",
"Cache-Control":"no-cache",
"Connection":"keep-alive"});
res.write("retry: 10000\n");
res.write("event: connecttime\n");
res.write("data: " + (new Date()) + "\n\n");
res.write("data: " + (new Date()) + "\n\n"); interval = setInterval(function() {
res.write("data: " + (new Date()) + "\n\n");
}, 1000); req.connection.addListener("close", function () {
clearInterval(interval);
}, false);
}
}).listen(80, "127.0.0.1");

PHP代码实例。

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache'); // 建议不要缓存SSE数据 /**
* Constructs the SSE data format and flushes that data to the client.
*
* @param string $id Timestamp/id of this connection.
* @param string $msg Line of text that should be transmitted.
*/
function sendMsg($id, $msg) {
echo "id: $id" . PHP_EOL;
echo "data: $msg" . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
} $serverTime = time(); sendMsg($serverTime, 'server time: ' . date("h:i:s", time()));

参考链接

转:SSE:服务器发送事件的更多相关文章

  1. SSE:服务器发送事件,使用长链接进行通讯

    概述 传统的网页都是浏览器向服务器“查询”数据,但是很多场合,最有效的方式是服务器向浏览器“发送”数据.比如,每当收到新的电子邮件,服务器就向浏览器发送一个“通知”,这要比浏览器按时向服务器查询(po ...

  2. 关于HTML5服务器发送事件(SSE)

    最近在看 W3School 上关于 HTML 5 的教程.在看到 HTML 5 服务器发送事件 ( SSE, server-sent event ) 时,没怎么弄明白示例代码是怎么回事,寻找其他教程, ...

  3. HTML5支持服务器发送事件(Server-Sent Events)-单向消息传递数据推送(C#示例)

    传统的WEB应用程序通信时的简单时序图: 现在Web App中,大都有Ajax,是这样子: HTML5有一个Server-Sent Events(SSE)功能,允许服务端推送数据到客户端.(通常叫数据 ...

  4. HTML 5 服务器发送事件

    接收 Server-Sent 事件通知 EventSource 对象用于接收服务器发送事件通知: 实例 var source=new EventSource("demo_sse.php&qu ...

  5. 【HTML5】Server-Sent服务器发送事件

    Server-Sent 事件 - 单向消息传递 Server-Sent 事件指的是网页自动获取来自服务器的更新. 以前也可能做到这一点,前提是网页不得不询问是否有可用的更新.通过服务器发送事件,更新能 ...

  6. HTML5学习(十一)---服务器发送事件

    参考教程:http://www.w3school.com.cn/html5/html_5_serversentevents.asp HTML5 服务器发送事件(server-sent event)允许 ...

  7. HTML5 服务器发送事件(Server-Sent Events)介绍

    w3cschool菜鸟教程 Server-Sent 事件 - 单向消息传递 Server-Sent 事件指的是网页自动获取来自服务器的更新. 以前也可能做到这一点,前提是网页不得不询问是否有可用的更新 ...

  8. HTML5 总结-服务器发送事件-9

    HTML 5 服务器发送事件 HTML5 服务器发送事件(server-sent event)允许网页获得来自服务器的更新. Server-Sent 事件 - 单向消息传递 Server-Sent 事 ...

  9. HTML 5 服务器发送事件、Input 类型、表单元素、表单属性

    HTML5 服务器发送事件(server-sent event)允许网页获得来自服务器的更新. Server-Sent 事件 - 单向消息传递 Server-Sent 事件指的是网页自动获取来自服务器 ...

随机推荐

  1. 【Android - 框架】之Dagger2+MVP的用法

    MVP模式本身相比于MVC模式就已经把View层和Controller层从Activity中进行了分离,将Model层和View层用Presenter层隔开,实现了初步的解耦.如果再加入Dagger2 ...

  2. grep:Binary file (standard input) matches

    grep "key" xxx.log时输出 Binary file xxx.log matches 百度了一下:grep觉得这是二进制文件.解决方式:grep -a. grep - ...

  3. Redhat 官方Performance_Tuning_Guide

    https://access.redhat.com/documentation/zh-CN/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Gui ...

  4. viewController启动方法分析

    viewController启动方法分析 转载:http://blog.csdn.net/dizzthxl/article/details/14170047 首先理清楚一个概念: 创建一个类和实例化一 ...

  5. Java源码中的发现:快速判断一个int值是几位数

    判断一个int值是几位数,要是我自己实现,估计又会想到除法和模运算了,偶然在java标准API源码中发现的写法,很强大. public class Test { final static int[] ...

  6. Programming a Spider in Java 源码帖

    Programming a Spider in Java 源码帖 Listing 1: Finding the bad links (CheckLinks.java) import java.awt. ...

  7. 实践过配置成功的VNC安装配置

    VNC安装步骤说明那个 1.安装图形界面    #yum install tigervnc-server tigervnc  2.启动VNCServer #vncserver 对应的关闭图形界面的命令 ...

  8. MEF依赖注入调试小技巧!

    自从哥的项目使用MEF以来,天天那个纠结啊,甭提了.稍有错误,MEF就报错,但就不告诉你哪错了,大爷的. 后来看了MEFX的相关调试方法,感觉也不太理想,根本不够直观的看到错误原因,也许是没有深入学习 ...

  9. c#迭代算法

    //用迭代算法算出第m个值 //1,1,2,3,5,8...;           //{1,0+1,1+1,1+2,2+3 ,3+5} static void Main(string[]   arg ...

  10. mysql 远程访问 配置

    sudo vi /etc/mysql/my.cnf 找到bind-address = 127.0.0.1 注释掉这行:#bind-address = 127.0.0.1 或者改为: bind-addr ...