目前可用来在前端浏览器上进行实时通信的功能的实现方式主要有 WebSocket、Poll、Long-poll 和 DDP 协议
WebSocket
WebSocket 是浏览器端和服务器端建立实时连接的一种通信协议,可以再服务器和浏览器端建立类似Socket方式的消息通信。目前 HTTP/1.1 支持使用 Upgrade 头域设置进行协议扩展切换,从而实现从 HTTP/1.1 协议切换到其他通信协议
来自客户端的一次请求,如下:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
来自服务端的一次响应,如下:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
上面的握手经过实现协议升级,切换为 WebSocket,方便服务端与客户端之间的双向数据实时通信
下面是 WebSocket 官方参考标准的消息数据帧结构
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
- FIN: 1 bit ,表示是消息的最后一帧,如果消息只有一帧那么第一帧也就是最后一帧
- RSV1,RSV2,RSV3:各 1 bit,必须是0,除非扩展定义为非零。如果接受到的是非零值但是扩展没有定义,则需要关闭连接
- Opcode: 4 bits,表示PayloadData的有效负荷,如果接受到未知的Opcode,接收方必须关闭连接
- Mask: 1 bit,掩码,定义payload数据是否进行了掩码处理,如果是1表示进行了掩码处理
Masking-key域的数据即是掩码密钥,用于解码PayloadData。客户端发出的数据帧需要进行掩码处理,所以此位是1 - Payload length: 7 bits,7 + 16 bits,7+64 bits,payload数据的长度,如果是0-125,就是真实的payload长度,如果是126,那么接着后面的2个字节对应的16位无符号整数就是payload数据长度;如果是127,那么接着后面的8个字节对应的64位无符号整数就是payload数据的长度
- Masking-key: 0到4字节,如果MASK位设为1则有4个字节的掩码解密密钥,否则就没有
- Payload data: 任意长度数据。包含有扩展定义数据和应用数据,如果没有定义扩展则没有此项,仅含有应用数据
需要注意的有: WebSocket 在网络中传输的最小单位为帧,数据的传输也可以理解为流式传输。兼容性主要是不支持 IE11 以下和 Android4.4 以下的浏览器
Poll & Long-poll
考虑到并非所有浏览器都支持 WebSocket 协议,所以就有必须回到现有的 HTTP 协议上考虑采用 Poll(轮询) 和 Long-poll(长轮询)的方案来应对实时通信的场景
Poll
Poll 可以理解为客户端采用定时向服务端发送请求轮询的方法,不断发送或拉取消息。如下图所示
+----------+ +----------+ +----------+
| client | | server | |msg server|
+----------+ +----------+ +----------+
|| || ||
|| 1 poll || ||
|| +-------------> || ||
|| || ||
|| <-------------+ || ||
|| || return ||
|| || <-------------+ ||
|| 2 poll || ||
|| +-------------> || ||
|| || ||
|| <-------------+ || ||
|| || return ||
|| || <-------------+ ||
|| 3 poll || ||
|| +-------------> || ||
|| || ||
|| <-------------+ || ||
|| || ||
|| || ||
++ ++ ++
客户端每隔一秒向服务端发送一次请求,在一秒内服务端更新的内容在下一次轮询中将被客户端拉取返回。Poll 方案缺点是实时性差,而且在没有新消息返回的时依然需要不断轮询,消耗系统资源
Long-poll
HTTP 请求可以设置一个较长的 Timeout 等待时间,这样每次轮询请求就可以维持一段较长的时间后再返回结果,这就是Long-poll(长轮询)的基本思路。服务端只要在这段长轮询时间内进行响应,请求便会立即返回,否则字段响应超时并重新发起一个长轮询,如下图所示
+----------+ +----------+ +----------+
| client | | server | |msg server|
+----------+ +----------+ +----------+
|| || ||
|| 1 long-poll || ||
|| +-------------> || ||
|| || ||
|| || ||
|| return || return ||
|| <-------------+ || <-------------+ ||
|| 2 long-poll || ||
|| +-------------> || ||
|| || ||
|| || ||
|| return || return ||
|| <-------------+ || <-------------+ ||
|| || ||
|| || ||
|| || ||
|| || ||
++ ++ ++
DDP
DDP(Distributed Data Protocal,分布式数据协议)是一种新型的客户端与服务端的实时通信协议。DDP是使用JSON的数据格式作为传输介质,其中使用DDP的有Meteor框架,作为其双向实时数据更新机制底层。
//创建服务端
const DDPClient = require('ddp');
const client = new DDPClient({
host: 'localhost',
port: 3000
});
//监听消息
client.on('message', function(data, flags){
console.log('[DDP消息]: ', data);
});
//创建连接
client.connect(function(){
client.subscribe('post',[],function(){
console.log('[post订阅消息]');
});
});
客户端可向服务端发起远程调用,也可以订阅服务端数据,在服务端数据变化时,服务端会向客户端发起通知触发浏览器响应的操作
总结
这次写的前端通信协议更多的是发生在浏览器这端,也就是客户端,考虑的仅仅是客户端与服务端直接的通信,如果是服务端之间的通信的话,情况也会不一样,所以留到下一篇再说
内容不多,大概就这样~
本文由 Chakhsu Lau 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。
很喜欢你的主题。后续还会更新吗?
后续还会适配为pwa~
大大,有时间可以说一下下方 I work with 那个是怎么弄的么 很喜欢 感谢!