websocket协议入门

背景

websocket是html5提出的新的协议规范,填补了无法长连接的空缺。在没有websocket之前,由于http是短连接,只能由客户端请求服务器,一些功能(即时通讯/处理耗时的请求等)只能通过轮询来做,不断的轮询服务器是否有新的消息。
websocket正是为了解决这个问题而生,websocket是一个长连接/全双工的协议。

优点

  • 不用频繁送HTTP请求,只需要发送一个HTTP请求进行websocket握手,接下来则可以利用该TCP连接通过websocket协议通讯,避免了传输多个HTTP Header的浪费。

  • 全双工通道,突破了HTTP请求时只能client请求server的限制,server可以直接push消息给client端。

  • 可以边生成数据边传递,不需要等数据生成完毕,提高了效率

  • websocket数据传输是基于数据帧的,可以分片传输,不需要怕数据太大包容纳不下。

过程

websocket协议包含三个过程。
1. 握手打开连接(使用HTTP协议,通过HTTP协议建立连接,以免服务器不支持websocket直接不予回应)
2. 数据传输
3. 握手结束连接

注意:以下大部分例子使用官网提供的demo进行测试,使用wireshark进行抓包

1. Opening handshake

Opening handshake使用HTTP协议,通过HTTP协议建立连接,以免服务器不支持websocket直接不予回应。
从最开始到现在一共有三种握手方法:
(1)基于flash的handshake,一般用于IE或者旧版chrome,没有加密
(2)基于md5,较早的握手方法,有两个key,使用md5加密
(3)基于sha1,协议版本需要是13或以上,现在主要是使用这个,所以这里只讨论这个。

当客户端想要和服务器建立websocket连接,客户端需要发送一个HTTP请求,服务器也会响应这个请求。
请求:

响应:
这里写图片描述

  • 请求中的这两个字段代表着客户端想将HTTP连接升级为websocket连接
 Connection: Upgrade
 Upgrade: websocket
  • 客户端会经过校验才确定和服务器创建websocket连接,这里需要关注请求中的Sec-WebSocket-Key和响应中的Sec-WebSocket-Accept
Sec-WebSocket-Key: MK5n+7rxCGBj608e1/VJQw==
Sec-WebSocket-Accept: ofJ3UpTzhgemcUGIgfEw7NmPbqw=

这里key和accept的关系是:
(1)key与一段特殊字符串拼接(”258EAFA5-E914-47DA-95CA-C5AB0DC85B11”)

 MK5n+7rxCGBj6O8e1/VJQw==258EAFA5-E914-47DA-95CA-C5AB0DC85B11

(2)再经过sha1运行得出160位的字符串

扫描二维码关注公众号,回复: 1918798 查看本文章
a1f2775294f38607a671418881f130ecd98f6eac

(3)将上面的hash值经过base64加密
注意此处,hash值是16进制模式,直接转换成二进制加密即可

‭‭101000011111001001110111010100101001...
↓
‭101000 011111 001001 110111 010100 101001 ...‬
↓
ofJ3UpTzhgemcUGIgfEw7NmPbqw=

最后得出来的值必须与accept的值一致,否则校验不通过。

2. 数据传输

当客户端校验成功,就会与服务端建立起websocket连接,可以开始传输数据。
使用客户端向服务端发送文本消息,可见websocket的数据包较小,这里来逐个分析数据包格式。

这里写图片描述

(1)前面四个bit为标识位
第一位为Fin,标识着此消息是否为最后一个数据包。如果数据太大被切分成多个包,则前面若干个包Fin为0,最后一个为1 。此处包比较小,可以容纳下数据,为1
后面3个bit暂时保留。

(2)4-7bit为Opcode,操作码
0x0:标识一个中间数据包
0x1:标识一个text类型数据包
0x2:标识一个binary类型数据包
0x3-7:保留
0x8:标识一个断开连接类型数据包
0x9:标识一个ping类型数据包
0xA:标识一个pong类型数据包
0xB-F:保留

(3)第8bit为Mask
标识着是否使用掩码,协议要求客户端发送数据必须使用掩码,Mask为1,服务器发送数据不使用掩码,Mask为0

(4)9-15bit为payload的长度
这7个bit固定用于显示paylaod长度,如果7个bit不够用,可以扩展最多至后面8个字节

  • 如果其值在0-125,则该值是payload的真实长度。
  • 如果值是126,则payload的真实长度为后面16位
  • 如果值是127,则payload的真实长度为后面64位

(5)payload Length后面是Mask-Key,占8位。
假如Mask为1,则payload会与mask-key做掩码运算(每8位做一次XOR运算)得到Masked-Payload用作实际传输。

总结一下,websocket数据包格式如下:
这里写图片描述

3. closing handshake

当某一端想要关闭连接时,发送close包,另一端回复一个同样的包即可。close包的格式与上面的数据传输的格式一致,Opcode为0x8。

当某一端发生异常,或者是Mask码不对(客户端发的不为1,或者服务端发的不为0),将会关闭连接,这时close包中会包含错误状态码,1002
这里写图片描述
更多的websocket状态码:https://segmentfault.com/a/1190000007587248

猜你喜欢

转载自blog.csdn.net/lblblblblzdx/article/details/80357543