went

17 天前

websocket 协议解析

本文作者:IMWeb went 原文出处:IMWeb社区 未经同意,禁止转载

1.使用websocket 场景

websocket作为用于双向通信的实用协议,在笔者最近做的全平台私信系统进行了应用。本次开发的私信系统与普遍理解的“发送-接受-发送”三个流程分开不一样,实现的是类似于QQ与微信的实时通信系统,需要做到收发消息实时化。

进行通信协议选定的时候,不能由服务器主动联系客户端,又因为每次通信都需要经过握手请求、响应步骤进行连接重建的http协议只能通过轮询进行伪双向通信,所以http协议首先被我们排除了,在HTML5下的协议websocket映入了我们的眼帘。

2.websocket 机制

首先要明确的一点是,支持websocket协议的客户端和服务器能够使用websocket协议进行双向通信,也就是客户端可以随时向服务器发送请求,服务器也能够随时向客户端发送请求。

跟http使用轮询实现不一样的是websocket一次连接成功后则可以重复进行请求和响应,更好地节省了服务器的资源与带宽。

websocket与http协议类似的是同样建立于tcp传输协议之上,通过tcp传输层进行数据传输。而客户端与服务器端一般使用的通信协议仍是http,我们要使用websocket协议进行通信则首先要建立起websocket连接,这个连接的建立依赖于http。

一个websocket连接首先发送http请求到服务器,注意比起平常的http请求多了4个字段,sec-WebSocket-* 为建立websocket协议的参数,upgrade字段才是重点,告诉服务器我这次的请求不是单纯的http请求,而是要求服务器升级连接并建立起websocket长连接。

服务器响应也根据特殊的请求头进行了特殊响应,首先101返回码表明本次连接的通信协议经过了转换并成功握手成功建立起了通信。connection字段和upgrade字段则表明本次通信协议进行了升级转换,转换的是websocket协议。

websocket的协议标识符为ws,从下图Request URL看到本次websocket连接的协议标识符为wws,这表示websocket连接是经过加密处理的。

建立了websocket连接后,只要客户端和服务器端任意一端不主动断开连接前,通信行为都是在一个持久连接上发起,后续数据与请求都通过帧序列的形式进行传输。

从chrome控制台的Websocket调试面板中可以看到,在一个websocket连接中多次请求都可以由服务器进行实时响应,实行实时上下行通信的能力得以见证。

3.websocket API

通过WebSocket构造函数可以创建websocket连接并返回提供管理该连接API的实例对象。

const ws = new WebSocket('wws://url');
websocket 属性与事件
事件&属性 定义
onopen 服务器端响应连接请求后,readyState状态置为OPEN时触发。标志着握手阶段已结束,可以进行收发消息。
onmessage 服务器端有消息到达时触发,可以接受文本和二进制数据。
onclose 连接关闭时,readyState状态置为CLOSED时触发。标志着服务器端与客户端不能再通信。
onerror 错误发生时触发,会导致连接关闭。
readyState websocket连接状态。CONNECTING(连接中) OPEN(连接成功) CLOSING(关闭中) CLOSED(已关闭)
protocol websocket连接协议。ws & wws
bufferedAmount 调用send方法后在发送队列缓存中的数据量,所有消息已发出则清零。
binaryType 当收到二进制数据时,用于表示该二进制数据的类型(blob & arraybuffer)
// 监听到open事件后,向服务器发送success文本。
ws.addEventListener('open', (e) => {
    ws.send('success!');
})
websocket 方法

(1) send 方法

// 文本数据
const text = 'i am text';

// 二进制数据
const blob = new Blob('i am blob');

ws.send(text);
ws.send(blob);

(2) close 方法

close方法可以传入两个参数 code 和 reason ,用于向服务器端说明关闭连接原因。

ws.close(1000, 'mission finished');

// 不传任何参数,默认code是1000,表示正常关闭
ws.close();

4. 小结

在需要实现双向实时通信的场景下,不妨直接使用websocket协议吧。但是目前IE8和IE9是不支持websocket的,要实现该功能还是只能通过http 的long polling 方式去实现。

以上是websocket的基础理论,希望了解后有助于大家的实践!

0条评论

    您需要 注册 一个IMWeb账号或者 才能进行评论。