WebSocket协议
WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。
它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
可以对照着这个报文来看
General:
Request URL: ws://192.168.0.104:8000/ws/admin/
Request Method: GET
Status Code: 101 Switching Protocols
Response Headers:
Connection: Upgrade
Sec-WebSocket-Accept: 2AoLKibh+f+uMBBcbiS8I2or8Gw=
Server: Daphne
Upgrade: WebSocket
Request headers:
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: Upgrade
Cookie: csrftoken=u4xfXVwoDR26wKzKChfHO0srE06phmAPOsxiAM6O13wypNY0RsoyTgi7JpHrQQy5; sessionid=wt20pel1fhojibrqylgn3y9jpouvhj4n
Host: 192.168.0.104:8000
Origin: http://192.168.0.104:8000
Pragma: no-cache
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: RG7L4nO1IRMXGWBqTsY/lw==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36
请求头中的重要字段
- Connection和Upgrade:表示客户端发起的是WebSocket请求
- Sec-WebSocket-Version:客户端所使用的的WebSocket协议版本号,服务端会确认是否支持该版本号
- Sec-WebSocket-Key:一个Base64编码值,由浏览器随机生成,用于升级request
- Sec-WebSocket-Extensions客户端想表达的协议级的扩展
响应头中的重要字段
- Status Code 101 Switching Protocols:切换协议,WebSocket协议通过HTTP协议来建立运输层的TCP连接
- Connection和Upgrade:表示服务端返回的是WebSocket响应
- Sec-WebSocket-Accept:表示服务器接受了客户端的请求,由Sec-WebSocket-Key计算得来
验证Sec-WebSocket-Key和Sec-WebSocket-Accept的关系
MDN:Protocol upgrade mechanism这篇文档中提到
If a Sec-WebSocket-Key header was provided, the value of this header is computed by taking the value of the key, concatenating the string “258EAFA5-E914-47DA-95CA-C5AB0DC85B11” to it, taking the SHA-1 hash of that concatenated string, resulting in a 20-byte value. That value is then base64 encoded to obtain the value of this property.
那我们进入到python环境中验证一下
cws@mypc:~$ python3
Python 3.6.9 (default, Nov 7 2019, 10:44:02)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> text = "RG7L4nO1IRMXGWBqTsY/lw==258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
>>> import hashlib
>>> import base64
>>> h = hashlib.sha1(text.encode())
>>> h.digest()
b'\xd8\n\x0b*&\xe1\xf9\xff\xae0\x10\\n$\xbc#j+\xf0l'
>>> base64.b64encode(h.digest())
b'2AoLKibh+f+uMBBcbiS8I2or8Gw='
>>>
可以看到,请求头中Sec-WebSocket-Key
拼接上字符串"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
的经过运算后得到的'2AoLKibh+f+uMBBcbiS8I2or8Gw='
正好就是响应头中的Sec-WebSocket-Accept
WebSocket协议的优缺点及应用场景
优点
- 支持双向通信,实时性更强
- 数据格式比较轻量,性能开销小,通信高效。
- 支持扩展。用户可以扩展协议或者实现自定义的子协议(比如支持自定义压缩算法等)
缺点
- 少部分浏览器不支持,浏览器支持的程度与方式有区别
- 长连接对后端处理业务的代码稳定性要求更高,后端推送功能相对复杂
- 成熟的HTTP生态下有大量的组件可以复用,WebSocket较少
应用场景
- 即时聊天通信,网站消息通知
- 在线协同编辑,如腾讯文档
- 多玩家在线游戏、视频弹幕、股票基金实时报价