websocket文档_WebSocket推送 原理扫盲到上手实践

      关于服务端推送技术,大家比较熟悉的可能就是轮询,但是轮询只能是由客户端先发起http请求。在HTTP1.1中的keep-alive方式建立的http连接,但是一个Request只能对应一个Response,而且这个Response是被动的,不能主动发起。

      为了在IM、股票等场景下,真正解决服务端实时向客户端推送数据的问题,出现了基于TCP的长连接通讯协议websocket。

        websocket协议本身需要注意的一共有两点:

        1.为了兼容现有浏览器的握手规范而借用了HTTP的协议来完成一部分握手。

        2.websocket是纯事件驱动的,一旦连接建立,通过监听事件可以处理到来的数据和改变的连接状态,数据都以帧序列的形式传输。服务端发送数据后,消息和事件会异步到达。websocket编程遵循一个异步编程模型,只需要对websocket对象增加回调函数就可以监听事件。

       下面来具体介绍一下websocket的这两点特征,先介绍基于回调函数的事件编程:

异步编程模型

如果大家想切身体验一下websocket,可以自己下载现成demo。地址:https://github.com/sockjs/sockjs-node/tree/v0.3.19(注意:请通过download下载文件的方式下载代码,不要直接clone,不然代码版本不一样)。不过为了更好地实现浏览器兼容性,demo中是通过sockjs-node库来实现websocket协议的底层协议。更多的sockjs的api请进一步参考git网页中sockjs-node的文档。

      本次用来演示的是example文件夹中的koa项目,在代码中大家可以着重理解上面提到的websocket需要注意的第二点,在代码中,主要是通过事件回调函数的方式来实现对消息的处理的。

      在服务器代码中首先为sockjs_echo变量赋值了一个websocket连接实例,定义接收到消息后的回调函数,即把接收到的message进行回写。然后启动了一个koa服务器,当被访问的时候返回一个index.html文件,作为webSocket的客户端。最后通过installHandlers方法,在访问路由/echo的时候为koa服务器增加websocket连接的回调处理。

var koa     = require('koa');
var sockjs  = require('sockjs');
var http    = require('http');
var fs      = require('fs');
var path    = require('path');

// 1. Echo sockjs server
var sockjs_opts = {sockjs_url: "http://cdn.jsdelivr.net/sockjs/1.0.1/sockjs.min.js"};
var sockjs_echo = sockjs.createServer(sockjs_opts);
sockjs_echo.on('connection', function(conn) {
    conn.on('data', function(message) {
        conn.write(message);
    });
});

// 2. koa server
var app = new koa();

app.use(function *() {
    var filePath = __dirname + '/index.html';
    this.type = path.extname(filePath);
    this.body = fs.createReadStream(filePath);
});

var server = http.createServer(app.callback());
sockjs_echo.installHandlers(server, {prefix:'/echo'});

server.listen(9999, '0.0.0.0');
console.log(' [*] Listening on 0.0.0.0:9999' );

      而在客户端实现如下,通过sockjs库实例化websocket连接实例后,通过onopen、onmessage、onclose这些回调函数来实现消息的发送、接收、连接关闭处理:

var sockjs_url = '/echo';
var sockjs = new SockJS(sockjs_url);

sockjs.onopen  = function()  {print('[*] open', sockjs.protocol);};
sockjs.onmessage = function(e) {print('[.] message', e.data);};
sockjs.onclose   = function()  {print('[*] close');};

form.submit(function() {
    print('[ ] sending', inp.val());
    sockjs.send(inp.val());
    inp.val('');
    return false;
});

借用HTTP协议完成握手

       启动koa服务后,我们访问http://0.0.0.0:9999/打开页面,可以在浏览器network选项卡中观察到连接的建立过程。在request的header中通过"Connection:Upgrade;Upgrade:websocket"字段表示浏览器通知服务器,如果可以,就升级到websocket协议。response中同样通过"Connection:Upgrade;Upgrade:websocket"来通知浏览器,服务端已经成功切换协议,返回状态码为101。

babcf9206f36272b84fde689b7730137.png

      我们此时可以试着在网页中输入一些内容来通过websocket来发送,还是在浏览器的Network选项卡中可以看到我们发送的消息和服务端回写回来的消息:

06fcd379d916c0e5bca896172289d5b8.png

      目前我们已经看到了一个简单的websocket实现,但是在websocket中传输的内容是不是还可以更加丰富一些,比如像http协议一样,添加上各种header字段来让我们实现出一些更加规范的语义协议?可以的。stomp协议就是这样的一个语义协议,可以在websocket的基础之上,通过stomp协议来更加规范地传输消息。

官方文档:http://jmesnil.net/stomp-websocket/doc/

翻译文档:https://blog.csdn.net/quanyuejie/article/details/53896140

      使用了stomp协议在websocket基础上传输消息的效果如下,我们可以看到在websocket的消息中,一个消息可以看作一个frame,每个frame中有自己的command和headers、body。比如在连接帧中发送了"CONNECT"的命令,后面accept-version作为headers来定义版本号,heart-beat来定义心跳等等这些功能,都可以看作是通过stomp协议来实现的:

2ca3dfd69c24ad015b9a3fe9a85985da.png

参考:

JS 服务器推送技术 WebSocket 入门指北  公众号:前端下午茶

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值