簡單聊聊WebSocket

1、概述

上一篇文章《淺析一次HTTP請求》咱們分析了簡單的一次 HTTP 請求具體是怎麼樣完成的,分析了 HTTP 協議的數據結構,如何鏈接,如何斷開,又是如何多路複用的,那麼今天咱們來聊聊另一個協議,WebSocket。因爲 WebSocket 的協議的內容很是多,本文只會取其冰山一角進行簡單闡述,不會鋪開詳細說。html

2、什麼是 WebSocket

2.1 WebSocket 產生的背景

在 WebSocket 協議出現之前,建立一個和服務端進雙通道通訊的 web 應用,須要依賴HTTP協議,進行不停的輪詢,這會致使一些問題:git

  • 服務端被迫維持來自每一個客戶端的大量不一樣的鏈接github

  • 大量的輪詢請求會形成高開銷,好比會帶上多餘的header,形成了無用的數據傳輸。web

因此,爲了解決這些問題,WebSocket 協議應運而生。算法

2.2 WebSocket 的定義

WebSocket 是一種在單個TCP鏈接上進行全雙工通訊的協議。 WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,容許服務端主動向客戶端推送數據。瀏覽器

在 WebSocket API 中,瀏覽器和服務器只須要完成一次握手,二者之間就直接能夠建立持久性的鏈接, 並進行雙向數據傳輸。(維基百科)緩存

3、WebSocket 的基礎幀結構分析

下圖是我參考 RFC6455 5.2章節畫的websocket 基礎幀的數據結構圖,接下里咱們重點解析下數據結構圖。安全

FIN:佔用1 bit,表示這是消息的最後一個片斷。第一個片斷也有多是最後一個片斷。bash

RSV1,RSV2,RSV3: 每一個1 bit服務器

必須設置爲0,除非擴展了非0值含義的擴展。若是收到了一個非0值可是沒有擴展任何非0值的含義,接收終端必須斷開WebSocket鏈接。

Opcode: 4 bit,操做碼,若是收到一個未知的操做碼,接收終端必須斷開WebSocket鏈接。

%x0 表示一個持續幀

​ %x1 表示一個文本幀

​ %x2 表示一個二進制幀

​ %x3-7 預留給之後的非控制幀

​ %x8 表示一個鏈接關閉包

​ %x9 表示一個ping包

​ %xA 表示一個pong包

​ %xB-F 預留給之後的控制幀

Mask: 1 bit,mask標誌位,定義「有效負載數據」是否添加掩碼。若是設置爲1,那麼掩碼的鍵值存在於Masking-Key中。

Payload length: 7 bits, 7+16 bits, or 7+64 bits,以字節爲單位的「有效負載數據」長度。

Masking-Key: 0 or 4 bytes,

​ 全部從客戶端發往服務端的數據幀都已經與一個包含在這一幀中的32 bit的掩碼進行過了運算。若是mask標誌位(1 bit)爲1,那麼這個字段存在,若是標誌位爲0,那麼這個字段不存在。 備註:載荷數據的長度,不包括mask key的長度。。

Payload data: 有效負載數據

爲何須要掩碼?

爲了安全,但並非爲了防止數據泄密,而是爲了防止早期版本的協議中存在的代理緩存污染攻擊(proxy cache poisoning attacks)等問題。

4、 抓包分析

4.1 DEMO展現及分析

我寫了一個DMEMO用來抓包分析 websocket,源代碼會放在文章末尾的連接。DEMO效果以下:

頁面提供鏈接與斷開功能,輸入本身的名字發送,服務端返回Hello,名字!功能很簡單,咱們先看看頁面的請求和響應。

請求:

響應:

這裏的請求與響應就是反應了 WebSocket 的一次握手,咱們根據上圖能夠簡單抽象一下 WebSocket 的請求和響應格式: 客戶端握手請求格式:

GET /chat HTTP/1.1
       Host: server.example.com
       Upgrade: websocket
       Connection: Upgrade
       Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
       Origin: http://example.com
       Sec-WebSocket-Protocol: chat, superchat
       Sec-WebSocket-Version: 13
複製代碼

服務端握手響應:

HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
        Sec-WebSocket-Protocol: chat
複製代碼

咱們重點說明下結果請求字段:

Upgrade:表示HTTP協議升級爲webSocket

connection:Upgrade 請求升級。

Sec-WebSocket-Key: 用於服務端進行標識認證,生成全局惟一id,GUID。

Sec-WebSocket-Version: 版本

Sec-WebSocket-Protocol: 請求服務端使用指定的子協議。若是指定了這個字段,服務器須要包含相同的字段,而且從子協議的之中選擇一個值做爲創建鏈接的響應。

Sec-WebSocket-Extensions: WebSocket的擴展。

Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= 生成的全局惟一id,GUID。

GUID的生成算法

算法思想:經過 Sec-WebSocket-Key 傳入的 值,dGhlIHNhbXBsZSBub25jZQ==,鏈接服務端生成的字符串,拼接格式以下

dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-
 C5AB0DC85B11
複製代碼

, 而後採用SHA-1哈希算法,而後用base64編碼生成最終的 Sec-WebSocket-Accept的值,生成的值就是

s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

複製代碼

(注意,這裏SHA1哈希算法生成的結果必須是二進制的哈希結果,好比

Python代碼中的

h = hashlib.sha1("dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
.digest()

複製代碼

若是用在線處理工具生成,生成的Hash是16進制的哈希,用 Base64就會生成錯誤結果)

4.2 抓包

我在DEMO中的操做流程以下:

  • 鏈接WebSocket
  • 發送「LUOZHOU」
  • 斷開鏈接

用 Wireshark 抓包以下:

咱們結合瀏覽器截圖和抓包截圖,發如今真正開啓 websocket 以前,瀏覽器會有兩次http請求,分別是:

A請求 GET /gs-guide-websocket/info?t=1551252237372 HTTP/1.1

B請求 GET /gs-guide-websocket/690/pdsz5x1q/websocket HTTP/1.1
複製代碼

根據 RFC6455 協議規定 WebSocket 只須要一次握手就能夠完成,因此咱們只須要分析第二次的http 握手請求,A請求應該是使用的框架層面本身實現。

咱們根據截圖能夠知道,B請求對應的響應是序號 192 的數據,返回碼是101,根據 HTTP 返回碼咱們能夠知道,服務器已經理解了客戶端的請求,並將經過Upgrade 消息頭通知客戶端採用不一樣的協議來完成這個請求。在發送完這個響應最後的空行後,服務器將會切換到在 Upgrade 消息頭中定義的那些協議,也就是升級爲 WebSocket 協議。因此接着193的包已經變成了 WebSocket 協議了。到這裏,WebSocket 的握手鍊接就已經完成了

接下來咱們分析下發送消息的流程,這裏你們確定會疑惑,就發送了一條消息,爲啥會有這麼多 WebSocket 的包呢?其實這裏多餘的包是框架層面進行發送的,好比要進行訂閱與發佈的註冊等等操做。因此真正使咱們操做的包就只有斷開鏈接的相關包和發送「LUOZHOU」的包

根據上圖咱們發現 序號229的包是一個文本類型的包,opcode:1,而後採用了掩碼處理,同時是最後一個處理包。咱們仔細發現全部客戶端發送服務端的包都會有[MASKED]標記,服務端返回的沒有,這就說明了從客戶端向服務端發送數據時,須要對數據進行掩碼操做;從服務端向客戶端發送數據時,不須要對數據進行掩碼操做。

5、總結

  • WebSocket 是爲了在 web 應用上進行雙通道通訊而產生的協議,相比於輪詢HTTP請求的方式,WebSocket 有節省服務器資源,效率高等優勢。

  • WebSocket 中的掩碼是爲了防止早期版本中存在中間緩存污染攻擊等問題而設置的,客戶端向服務端發送數據須要掩碼,服務端向客戶端發送數據不須要掩碼。

  • WebSocket 中 Sec-WebSocket-Key 的生成算法是拼接服務端和客戶端生成的字符串,進行SHA1哈希算法,再用base64編碼。

  • WebSocket 協議握手是依靠 HTTP 協議的,依靠於 HTTP 響應101進行協議升級轉換。

DEMO代碼

6、參考

[1]RFC6455

[2]WebSocket 協議 RFC 文檔(全中文翻譯)

[3]WebSocket協議:5分鐘從入門到精通

相關文章
相關標籤/搜索