前端通信协议的一些了解

in Notes with 3 comments

目前可用来在前端浏览器上进行实时通信的功能的实现方式主要有 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 ...                |
+---------------------------------------------------------------+

需要注意的有: 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订阅消息]');
  });
});

客户端可向服务端发起远程调用,也可以订阅服务端数据,在服务端数据变化时,服务端会向客户端发起通知触发浏览器响应的操作

总结

这次写的前端通信协议更多的是发生在浏览器这端,也就是客户端,考虑的仅仅是客户端与服务端直接的通信,如果是服务端之间的通信的话,情况也会不一样,所以留到下一篇再说

内容不多,大概就这样~

Responses
  1. 4kb

    很喜欢你的主题。后续还会更新吗?

    Reply
    1. @4kb

      后续还会适配为pwa~

      Reply
  2. 大大,有时间可以说一下下方 I work with 那个是怎么弄的么 很喜欢 感谢!

    Reply