這篇文章通過抓包分析?WebSocket
?協議的細節,學習一下?WebSocket
?執行流程。
1.WebSocket 流程說明
(1)客戶端和服務器之間完成三次握手建立?
TCP
?連接(TLS/SSL)握手。(2)客戶端發起?
HTTP
?請求和服務器之間建立?WebSocket
?握手。(3)
WebSocket
?連接建立之后,雙方通信是基于?TCP
?連接的,此后不需要?HTTP
?協議了。(4)完成?
WebSocket
?握手之后,就可以發送消息內容了。
2.HTTP 建立 WebSocket 握手(HTTP 升級到 WebSocket)
Tips:其中紅色部分為必須,完成如上圖所示過程即建立了?
WebSocket
?連接,Sec-WebSocket-Key: 5C2dTYo3LMpWd/H+Nix4HQ==\r\n
?表示建立握手生成的隨機串。
2.1 如何證明握手被服務器接受
從上圖可以看到構建?WebSocket
?握手的時候,發送了一個?Sec-WebSocket-Key
,
#請求中的 Sec-WebSocket-Key 隨機數
Sec-WebSocket-Key:c3SkgVxVCDhVCp69PJFf3A==
#響應中的 Sec-WebSocket-Accept 證明值
Sec-WebSocket-Accept:YzgwZjRlZTcxMThiYTdjNDliYzAyNTdmZmNlN2E5MzBmYzNiYTQ0Mg==
2.2 Sec-WebSocket-Accept 證明值構造規則
GUID(RFC4122):258EAFA5-E914-47DA-95CA-C5AB0DC85B11
值構造規則:BASE64(SHA1(Sec-WebSocket-Key+GUID))
拼接值:c3SkgVxVCDhVCp69PJFf3A==258EAFA5-E914-47DA-95CA-C5AB0DC85B11
SHA1值:c80f4ee7118ba7c49bc0257ffce7a930fc3ba442
BASE64值:YzgwZjRlZTcxMThiYTdjNDliYzAyNTdmZmNlN2E5MzBmYzNiYTQ0Mg==
2.3 抓包數據
3.消息與數據幀說明
Message 消息:1 條消息由一個或者多個幀組成,這些數據幀屬于同一類型,代理服務器可能合并、拆分消息的數據幀。
Frame 數據幀:持續幀、文本幀、二進制幀
4.WebSocket 協議格式
4.1 WebSocket 協議的特點
基于幀:不是基于流(HTTP、TCP)
每一幀要么承載字符數據,要么承載二進制數據
基于瀏覽器的同源策略,可以使用?
Access-Control-Allow-Origin
?等頭部基于?
URI
、子協議支持同主機同端口上的多個服務
4.2 幀格式示意圖
Tips:圖中藍色的?
2
?字節是必然存在的幀首部。
抓取到的包數據如下圖:
Tips:可以在百度搜索?
WebSocket 在線測試
,然后使用?Wireshark
?工具抓取。
4.3 幀類型
從上圖抓取到的數據包可以看到幀首部中有?Opcode
,它表示?幀類型
,下面列出不同類型的幀對應的?Opcode
?的值:
持續幀:0
非控制幀:1:文本幀,2:二進制幀,3-7:為非控制幀保留
控制幀:8:關閉幀,9:心跳幀ping,A:心跳幀pong,B-F:為控制幀保留
Tips:從?
3.2
?中可以看出?Opcode
?的值為?1
,表示文本幀。
4.4 MASK 掩碼作用
從上面的圖中可以看到?WebSocket
?每次發送消息的時候幀首部會有MASK
?掩碼,如下圖所示:
Tips:
MASK
?的作用是為了防止緩存污染攻擊
,防止偽造?WebSocket
?請求。
4.5 ABNF 描述的幀格式
ws-frame = frame-fin;1 bit int length
frame-rsv1;1 bit in length
frame-rsv2;1 bit in length
frame-rsv3;1 bit in length
frame-masked;1 bit in length
frame-payload-length;3 種長度
[frame-masking-key];32 bits in length
frame-payload-data;n*8 bits in;length,where;n >= 0
5.如何保持會話心跳
HTTP
?長連接是基于定時器維持的會話,若在定時器設置的時間范圍內,還沒有數據到達,就會自動斷開,而?WebSocket
?連接保持會話是基于心跳的;
5.1 心跳幀
心跳幀是可以穿插在數據幀中傳輸的
ping 幀:
Opcode=9
,可以含有數據pong幀:
Opcode=A
,必須與?ping
?幀數據相同
6.如何關閉 WebSocket 會話
6.1 關閉 WebSocket 會話
控制幀中的關閉幀:在 TCP 連接之上的雙向關閉。
發送關閉幀后,不能再發送任何數據。
接收關閉幀之后,不再接收任何到達的數據。
TCP 連接意外中斷也會關閉 WebSocket。
6.2 關閉幀的格式
關閉幀:
Opcode=8
。可以含有數據,但僅用于解釋關閉會話的原因,前 2 字節為無符號整型,遵循 mask 掩碼規則。
6.3 關閉幀抓包
Tips:從抓包軟件中可以看出?
TCP
?連接是在?WebSocket
?關閉之后再關閉的。