WebSocket 协议初探

公司项目使用WebSocket作为主要的请求方式,知其然也要知其所以然,会用也需要知道它的基本原理,所以写此文章分享下自己的浅见,文章主要包括以下内容:

  • WebSocket是什么
  • WebSocket和Socket区别
  • 建立连接
  • 数据帧格式
  • 发送数据
聊天Demo代码: github.com/madaoCN/Web… 包含tornado写的 Server 和 Client 脚本 和 简单ws使用实例的IOS代码
WebSocket是什么WebSocket是一种在单个 TCP 连接上进行 全双工 通信的协议,WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据 。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输 。WebSocket协议在2011年由 IETF 标准化为 RFC 6455
1. 优势
  • 全双工,服务器可以主动推送数据给客户端,持久连接,实时性强
  • 省流量,协议控制的数据包头部较小,只需要进行一次完整的http握手,后续升级为WebSocket进行通信,而HTTP的header一般有几十字节,而且每次通信都需要携带完整的头部
  • 不仅可以发送文本,也可以发送二进制,对二进制数据比较友好
WebSocket和Socket联系Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口, 而WebSocket和Http一样是属于应用层协议 。
WebSocket 协议初探

文章插图
 
当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接 。
建立连接Websocket 握手过程复用了HTTP协议的信道,然后对服务进行升级,后续就使用Websocket协议进行通信,所以只需要一次 HTTP 握手,服务端就能一直与客户端保持通信,直到关闭连接 。
一、升级请求
GET / HTTP/1.1Host: 192.168.1.250:6767Sec-WebSocket-Version: 13Upgrade: websocketSec-WebSocket-Key: cNtBvwgrxXtqDppb/0mcMw==Connection: UpgradeOrigin: http://192.168.1.250:6767与HTTP报文不太一样的主要是 Connection: Upgrade : 标识要升级协议 Upgrade: websocket : 升级到 Websocket 协议 Sec-WebSocket-Version: 13 : 标明WebSocket协议的版本号 Sec-WebSocket-Key: cNtBvwgrxXtqDppb/0mcMw== 随机生成的 ,与服务端响应 Sec-WebSocket-Accept 字段对应,提供基本的防护,防止恶意或者无意的连接,
二、服务端响应报文
HTTP/1.1 101 Switching ProtocolsUpgrade: websocketSec-Websocket-Accept: hutW70GFRNI1vI45roqiU0Lu33A=Server: TornadoServer/5.0.2Connection: UpgradeSec-Websocket-Accept : 是根据客户端 Sec-WebSocket-Key 计算而来的
计算方法为:
258EAFA5-E914-47DA-95CA-C5AB0DC85B11简单的Python代码验证
#coding=utf8import hashlibimport base64if __name__ == "__main__":sec_key = "cNtBvwgrxXtqDppb/0mcMw=="static_key = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"contact_key = sec_key + static_keysha1_rt = hashlib.sha1(contact_key).digest()print sec_keyprint base64.encodestring(sha1_rt)
WebSocket 协议初探

文章插图
 
三、抓包验证
使用WireShark对WebSocket连接过程抓包
WebSocket 协议初探

文章插图
 
很直观的可以看到 HTTP三次握手 -> 升级协议 -> 使用WebSocket通信 的过程
WebSocket 协议初探

文章插图
 

WebSocket 协议初探

文章插图
 
Websocket升级协议报文也与上文一致,大家可以自行运行Demo代码,然后使用WireShark进行抓包验证请求过程和报文
数据帧格式如果我们数据帧格式都不清楚的话,更遑论说了解WebSocket协议了
数据帧概览数据帧(frame)是WebSocket通信的基本单位,一个消息由一个或者多个帧组成,内容包括标志位,操作码,掩码,数据长度等
01230 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 ...| +---------------------------------------------------------------+


推荐阅读