服务器推送技术

在做前端页面渲染时,经常会遇到有的组件需要跟随数据的变化而实时的变化,例如:一个线上报名系统,总人数有一定限制,所以要实时的展现已经报名的人数,应该怎么实现呢?最基本有如下3种方案:

  • Ajax轮询
  • Ajax长轮询(comet)
  • websocket长连接

Ajax轮询

优点

实现简单,利用XHR,通过setInterval定时向后端发送请求。

缺点

会造成数据在一小段时间内不同步和大量无效的请求,增加后端处理压力.

1
2
3
4
5
6
7
8
setInterval(function() {
$.ajax({
url: 'https://www.baidu.com/',
success: function() {
//success code
}
});
}, 3000);

Ajax长轮询(comet)

在Ajax轮询的基础上做的一点改进,在后端数据没有更新的时候不再返回空响应,而且后端一直保存连接,直到后端有数据变化,则相应请求并且关闭连接,前端收到数据,马上再次向后端发起请求,并处理刚刚收到的数据。

通常的做法是,在服务器的程序中加入一个死循环,在循环中监测数据的变动。当发现新数据时,立即将其输出给浏览器并断开连接,浏览器在收到数据后,再次发起请求以进入下一个周期。

1
2
3
4
5
6
7
8
9
function async() {
$.ajax({
url: 'http://api.3g.qq.com',
success: function() {
async();
//success code
}
});
}

websocket长连接

WebSocket是html5中的协议,支持持久连接。http协议不支持持久连接,http1.0和http1.x都不支持持久性连接,http1.1中的keep-alive将多个http请求合并为1个。

WebSocket通信协议包含两个部分,一是开放性HTTP握手连接协商连接参数,二是二进制消息分帧机制(接收消息的文本和二进制数据传输)。它是一个独立完善的协议,也可以在浏览器之外实现。

HTTP的生命周期通过Request来界定,也就是Request一个response,那么在http1.0协议中这次请求就结束了;在http1.1中进行了改进,是有一个connection:keep-alive,也就是说在一个http连接里可以发送多个request,接收多个response。

Websocket是基于http协议的,或者说借用了http协议来完成部分握手,在握手阶段和http是相同的,请求头中多了两个属性:upgrade,connection

1
2
Upgrade: websocket
Connection: Upgrade

HTTP升级协商

WebSocket协议提供了很多强大的特性:基于消息的通信、自定义的二进制分帧层、子协议协商、可选的协议扩展,等等。即在交换数据之前,客户端必须与服务器协商适当的参数以建立连接。

利用HTTP完成握手有几个好处。首先,让WebSockets与现有HTTP基础设施兼容:WebSocket服务器可以运行在80和443 端口上,这通常是对客户端唯一开放的端口。其次,让我们可以重用并扩展HTTP的Upgrade流,为其添加自定义的WebSocket首部,以完成协商。

请求头信息

Connection:Upgrade Sec-WebSocket-Key:eDCPPyPQZq7PiwRcx8SPog== Sec-WebSocket-Version:13 Upgrade:websocket

响应头信息

HTTP/1.1 101 Switching Protocols Connection:Upgrade Sec-WebSocket-Accept:/ZVAP3n6XuqDUoDp416PYUO+ZJc= Upgrade:websocket

最后,前述握手完成后,如果握手成功,该连接就可以用作双向通信信道交换WebSocket消息。到此,客户端与服务器之间不会再发生HTTP通信,一切由WebSocket 协议接管。

具体使用方法,本文采用node.js中的Socket.IO来进行说明:

  1. 服务端创建socket.io的实例
1
2
3
4
5
6
7
8
9
10
11
var app = require('express')(); 
var http = require('http').Server(app);
var io = require('socket.io')(http);//创建实例

app.get('/', function(req, res){ res.sendfile('index.html'); });

io.on('connection', function(socket){
console.log('a user connected');
});// 监听前端连接

http.listen(3000, function(){ console.log('listening on *:3000'); });
  1. 数据传输
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 前端客户端向后端发送数据:
socket.emit('chat message', $('#m').val());

// 后端接收数据:

io.on('connection', function(socket){
socket.on('chat message', function(msg){
console.log('message: ' + msg); });
});

// 后端向前端发送数据:

io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg); });
});

// 前端接收数据:
socket.on('chat message', function(msg){ console.log(msg); });
本文结束感谢您的阅读

本文标题:服务器推送技术

文章作者:陈宇(cosyer)

发布时间:2018年07月05日 - 20:07

最后更新:2020年07月02日 - 19:07

原始链接:http://mydearest.cn/%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%8E%A8%E9%80%81%E6%8A%80%E6%9C%AF.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!