与 Web 服务器通信 - SSE
-
XMLHttpRequest:能够从客户端发送请求到服务器端并且得到响应。一个小demo在这里
但XHR不适合快速来回发送消息(如聊天室),并且无法将这一次调用和下一次调用联系起来(每次发起请求,服务器都要确定请求来自何方)。 -
轮询:浏览器定期向服务器发送消息并接受服务器回答是否有数据更新。(考虑轮询间隔时间过长/过短的问题)
-
COMET(长轮询):在每次请求的时候,服务器端保持该连接在一段时间内处于打开状态,而不是在响应完成之后立即关闭。
在打开状态的这一段时间里,有数据更新可以立即得到响应。
上一个长连接关闭之后,浏览器立即打开一个新的长连接继续请求。 -
COMET(流):浏览器向服务器发送一个请求,而服务器保持连接打开,然后周期性向浏览器发送数据。
-
Server-Sent events:适合服务器端向客户端不断的数据推送,更容易实现了comet。但整个通信完全单向,无法知道浏览器是否响应。
-
WebSocket:浏览器能够保持对Web服务器打开的连接,从而与服务器长时间交换数据。适合聊天室、大型多人游戏、端到端写作工具等。
Server-sent events
浏览器端实现:
// 创建 EventSource 对象
var url = "http://localhost:8080";
var source = new EventSource(url);
// 监听并绑定, 当收到服务器端发送的事件时触发
source.onmessage = receiveMessage;
function receiveMessage(e) { console.log(e.data); }
// 发生错误触发
source.onerror = errorOccured;
// 关闭连接
source.close();
服务器端实现(nodeJs版):
var http = require("http");
http.createServer(start).listen(8888);
function start(req, res) {
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Access-Control-Allow-Origin": "http://localhost:8080"
});
setInterval(function(){
var content = "data:" + Date() + "\n\n";
res.write(content);
}, 1000);
}
这里:
- 响应的内容类型为 "text/event-stream"
- 响应内容可以看成是一个事件流,由不同的事件所组成。
- 我这里发起了跨域请求,所以响应头需要包含 Access-Control-Allow-Origin, 用来指定允许哪些域访问现在的URL
每个事件组成:
- 类型(event):声明事件的类型
- 数据(data):以 data 开头的行可以出现多次,所有这些行都是该事件的数据。
每个 data 后以 "\n" 分隔,一个事件的数据以 "\n\n" 结束。 - 可选的标识符(id):声明事件的标识符。
如果服务器端返回的数据中包含了事件标识符id,浏览器会记录最近一次接收到的id。
如果与服务器端的连接中断,当浏览器端再次进行连接时,会通过 HTTP 头"Last-Event-ID"来声明最后一次接收到的id。 服务器端可以通过浏览器端发送的事件标识符id来确定从哪个事件开始来继续连接。 - 等待时间(retry):声明浏览器在连接断开之后,进行再次连接之前的等待时间
比如说如下:
data: first event
data: second event
id: 100
event: myevent
data: third event
id: 101
: this is a comment
data: fourth event
data: fourth event continue
OK 基本实现就是这样啦~~ 点击查看代码
但是但是,SSE 是不支持的IE的!!接着看看IE上的实现吧!
IE8+的支持
通过 XDomainRequest 发出跨域 AJAX 请求, 出于安全考虑会有严格限制:
-
返回 Access-Control-Allow-Origin 头:
指定允许访问的域 Access-Control-Allow-Origin. -
不能包含自定义的 HTTP 头:
限制了不能使用 Last-Event-ID 头来声明浏览器端最近一次接收到的事件的标识符id.
需要使用 GET 请求的参数或 POST 请求的内容体来传递标识符. -
对于浏览器端发送的"text/plain"类型的参数进行解析:
XDomainRequest 对象的请求内容类型(Content-Type) 只能是"text/plain".
意味着在是使用POST请求时, 只能在服务器端对原始的请求内容进行解析, 获得其中的参数值. -
XDomainRequest 对象发出的请求中不包含任何与用户认证相关的信息(如cookie)
需要通过 session 的 ID等其他方式来传递用户认证信息
posted on 2015-11-12 21:56 travelling-wxy 阅读(376) 评论(0) 编辑 收藏 举报