websocket原理学习

90 阅读5分钟

一、http vs websocket

1、http协议

1、主要关注:客户端==>服务器(获取资源)

2、特点:无状态协议,每个请求都是独立的, 请求应答模式, 服务端无法主动给客户端推送消息 (单工,半双工,全双工),http受浏览器同源策略的影响

2、websocket

特点:双向通信 (全双工协议),每次不用重新建立链接,可以一直相互通信,发送的消息增加帧非常小,支持多种数据格式,天生支持跨域通信

二、不用websocket 以前是怎样实现双向通信

1、轮询

每隔一段时间发送请求

前端

image.png

后端

image.png

缺点

1、竞速问题: 无法保证请求的先后顺序,可能会出现多个请求返回的时候同时修改资源。

2、频繁的网络请求 请求数目多 导致服务端增加负载,客户端发请求也会出现性能问题

3、http在发送的时候 会增加http报文 (鉴权,内容类型) 额外的数据消耗

4、实时性比较低,如果服务度1s内变了3次,前端是每隔1s发送的请求,数据会有错误

优点

实现容易; 不适合实时性比较的高的,低并发

2、长轮询

客户端发送请求后,服务端响应后,再发下一个请求

前端

image.png

后端

image.png

长轮询相比较短轮询 (希望实时性更强)

1、如果实时性强了,也会造成频繁的网络请求

2、链接堆积问题 这些链接都需要在服务端中保持打开, 占用服务端资源

3、实时性高了,但是要求服务端的并发能力必须强

3、iframe

前端

image.png 后端

image.png

4、sse

前端

image.png

后端 image.png

二、websocket数据帧

image.png


- FIN:1个比特 如果是1,表示这是消息(message)的最后一个分片(fragment),如果是0,表示不是是消息(message)的最后一个分片(fragment)
- RSV1, RSV2, RSV3:各占1个比特。一般情况下全为0。当客户端、服务端协商采用WebSocket扩展时,这三个标志位可以非0,且值的含义由扩展进行定义。如果出现非零的值,且并没有采用WebSocket扩展,连接出错。
- Opcode: 4个比特。操作代码,Opcode的值决定了应该如何解析后续的数据载荷(data payload)。如果操作代码是不认识的,那么接收端应该断开连接(fail the connection)
  - %x0:表示一个延续帧。当Opcode为0时,表示本次数据传输采用了数据分片,当前收到的数据帧为其中一个数据分片。
  - %x1:表示这是一个文本帧(frame)
  - %x2:表示这是一个二进制帧(frame)
  - %x3-7:保留的操作代码,用于后续定义的非控制帧。
  - %x8:表示连接断开。
  - %x9:表示这是一个ping操作。
  - %xA:表示这是一个pong操作。
  - %xB-F:保留的操作代码,用于后续定义的控制帧。
- Mask: 1个比特。表示是否要对数据载荷进行掩码操作
  - 从客户端向服务端发送数据时,需要对数据进行掩码操作;从服务端向客户端发送数据时,不需要对数据进行掩码操作,如果服务端接收到的数据没有进行过掩码操作,服务端需要断开连接。
  - 如果Mask是1,那么在Masking-key中会定义一个掩码键(masking key),并用这个掩码键来对数据载荷进行反掩码。所有客户端发送到服务端的数据帧,Mask都是1。
- Payload length:数据载荷的长度,单位是字节。为7位,或7+16位,或7+64位。
  - Payload length=x为0~125:数据的长度为x字节。
  - Payload length=x为126:后续2个字节代表一个16位的无符号整数,该无符号整数的值为数据的长度。
  - Payload length=x为127:后续8个字节代表一个64位的无符号整数(最高位为0),该无符号整数的值为数据的长度。
  - 如果payload length占用了多个字节的话,payload length的二进制表达采用网络序(big endian,重要的位在前)
- Masking-key:0或4字节(32位) 所有从客户端传送到服务端的数据帧,数据载荷都进行了掩码操作,Mask为1,且携带了4字节的Masking-key。如果Mask为0,则没有Masking-key。载荷数据的长度,不包括mask key的长度
- Payload data:(x+y) 字节
  - 载荷数据:包括了扩展数据、应用数据。其中,扩展数据x字节,应用数据y字节。
  - 扩展数据:如果没有协商使用扩展的话,扩展数据数据为0字节。所有的扩展都必须声明扩展数据的长度,或者可以如何计算出扩展数据的长度。此外,扩展如何使用必须在握手阶段就协商好。如果扩展数据存在,那么载荷数据长度必须将扩展数据的长度包含在内。
  - 应用数据:任意的应用数据,在扩展数据之后(如果存在扩展数据),占据了数据帧剩余的位置。载荷数据长度 减去 扩展数据长度,就得到应用数据的长度。

三、简单实现原理流程

Header处理

2、将http协议升级为websocket协议(websocket第一次握手是通过http协议完成的)

3、websocket第一次握手时,客户端会产生一个随机的key,服务端会对key进行加密处理,并响应(Sec-Websocket-Accept)

Payload处理

1、判断FIN是否为1,为1说明数据传输结束

2、根据Opcode判断数据类型

3、根据mask判断是否需要掩码

4、如果需要掩码,则对数据根据掩码得出内容

代码实现

Header部分 image.png Payload部分

image.png