Webscoket是Web浏览器和服务器之间的一种全双工通信协议。一旦Web客户端与服务器建立起连接,之后的全部数据通信都通过这个连接进行。通信过程中,可互相发送JSON、XML、HTML或图片等任意格式的数据。
WS(WebSocket)与HTTP协议比较:
都是基于TCP的应用层协议; 都使用Request/Response模型进行连接的建立; 在连接的建立过程中对错误的处理方式相同,在这个阶段WS可能返回和HTTP相同的返回码; 都可以在网络中传输数据。
不同之处
WS使用HTTP来建立连接,但是定义了一系列新的header域,这些域在HTTP中并不会使用;
WS的连接不能通过中间人来转发,它必须是一个直接连接;
WS连接建立之后,通信双方都可以在任何时刻向另一方发送数据;
WS连接建立之后,数据的传输使用帧来传递,不再需要Request消息;
WS的数据帧有序。
WS整个通信过程如下图所示:
websocket是基于TCP的一个应用协议,与HTTP协议的关联之处在于websocket的握手数据被HTTP服务器当作HTTP包来处理,主要通过Update request HTTP包建立起连接,之后的通信全部使用websocket自己的协议。
**请求:**TCP连接建立后,客户端发送websocket的握手请求,请求报文头部如下:
GET /uin=xxxxxxxx&app=xxxxxxxxx&token=XXXXXXXXXXXX HTTP/1.1 Host: server.example.cn:443 Connection: Upgrade Pragma: no-cache Cache-Control: no-cache User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Upgrade: websocket Sec-WebSocket-Version: 13 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: user_id=XXXXX Sec-WebSocket-Key: 1/2hTi/+eNURiekpNI4k5Q== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits Sec-WebSocket-Protocol: binary, base64
第一行为为请求的方法,类型必须为GET,协议版本号必须大于1.1
Upgrade字段必须包含,值为websocket
Connection字段必须包含,值为Upgrade
Sec-WebSocket-Key字段必须包含 ,记录着握手过程中必不可少的键值。
Sec-WebSocket-Protocol字段必须包含 ,记录着使用的子协议
Origin(请求头):Origin用来指明请求的来源,Origin头部主要用于保护Websocket服务器免受非授权的跨域脚本调用Websocket API的请求。也就是不想没被授权的跨域访问与服务器建立连接,服务器可以通过这个字段来判断来源的域并有选择的拒绝。
**响应:**服务器接收到请求后,返回状态码为101 Switching Protocols 的响应。
HTTP/1.1 101 Switching Protocols Server: WebSockify Python/2.6.6 Date: Wed, 27 May 2020 03:03:21 GMT Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: hXXXXXXXXXXXXXXxGmM= Sec-WebSocket-Protocol: binary
Sec-WebSocket-Accept字段是由握手请求中的Sec-WebSocket-Key字段生层的。
握手成功后,通信不再使用HTTP协议,而采用WebSocket独立的数据帧。如下图所示,为协议帧格式:
FIN,指明Frame是否是一个Message里最后Frame(之前说过一个Message可能又多个Frame组成);1bit,是否为信息的最后一帧 RSV1-3,默认是0 (必须是0),除非有扩展定义了非零值的意义。 Opcode,这个比较重要,有如下取值是被协议定义的 0x00 denotes a continuation frame 0x01 表示一个text frame 0x02 表示一个binary frame 0x03 ~~ 0x07 are reserved for further non-control frames,为将来的非控制消息片段保留测操作码 0x08 表示连接关闭 0x09 表示 ping (心跳检测相关) 0x0a 表示 pong (心跳检测相关) 0x0b ~~ 0x0f are reserved for further control frames,为将来的控制消息片段保留的操作码 Mask,这个是指明“payload data”是否被计算掩码。这个和后面的Masking-key有关,如果设置为1,掩码键必须放在masking-key区域,客户端发送给服务端的所有消息,此位的值都是1; Payload len,数据的长度, Masking-key,0或者4bit,只有当MASK设置为1时才有效。,给一个Websocket中掩码的意义 Payload data,帧真正要发送的数据,可以是任意长度,但尽管理论上帧的大小没有限制,但发送的数据不能太大,否则会导致无法高效利用网络带宽,正如上面所说Websocket提供分片。 Extension data:扩展数据,如果客户端和服务端没有特殊的约定,那么扩展数据长度始终为0 Application data:应用数据,