Fork me on GitHub

服务器端推送技术总结

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

    技术方案:

    1.Ajax轮询

    2.Ajax长轮询

    3.WebSocket

    Ajax轮询

    实现简单,利用XHR,通过setInterval定时向后端发送请求,优点是,实现非常简单;缺点是会造成数据在一小段时间内不同步和大量无效的请求,增加后端处理压力.

setInterval(function() {
    $.ajax({
        url: 'https://www.baidu.com/',
        success: function() {
            //success code
        }
    });
}, 3000);

  Ajax长轮询

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

function async() {
    $.ajax({
        url: 'http://api.3g.qq.com',
        success: function() {
            async();
            //success code
        }
    });
}

WebSocket

WebSocket是html5出来的东西(协议),也就是说http协议没有变化,或者说没关系,但http是不支持久链接的,WebSocket其实是一个新协议,跟http协议基本没有关系,只是为了兼容现有浏览器的握手规范而已。

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

HTTP升级协商

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

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

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');
});

前端创建websocket连接:

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io();
</script>

2.数据传输

前端向后端发送数据:

 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);
  });

 

posted @ 2017-02-10 15:39  sylven'as  阅读(5447)  评论(0编辑  收藏  举报