websocket 建立過程以及數據幀分析

websocket 建立過程

image

客戶端請求

  • Connection: Upgrade 表示要升級協議
  • Upgrade: websocket 告訴服務器要升級爲 websocket 協議
  • Sec-WebSocket-Version: 13 表示 websocket 的版本。如果服務端不支持該版本,需要返回一個Sec-WebSocket-Versionheader,裏面包含服務端支持的版本號。
  • Sec-WebSocket-Key:客戶端隨機生成的一個base64編碼,與後面服務端響應頭配套,提供基本的防護,防止無意的連接。
GET /chat HTTP/1.1     
Host: server.example.com     
Upgrade: websocket     
Connection: Upgrade     
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==     
Sec-WebSocket-Protocol: chat, superchat     
Sec-WebSocket-Version: 13     
Origin: http://example.com

服務器響應

  • 服務器返回 101 狀態碼,並切換爲 WebSocket 協議建立全雙工連接
  • Sec-WebSocket-Accept:客戶端請求頭的 Sec-Websocket-Key 與 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 拼接,通過 SHA1 算摘要,最後轉爲 base64 字符串返回。

所謂防止無意的連接是指,http 客戶端不小心請求了 websocket 服務。

HTTP/1.1 101 
Switching Protocols     
Upgrade: websocket     
Connection: Upgrade     
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=     
Sec-WebSocket-Protocol: chat

數據幀分析

圖來自掘金-黃Java-【譯】WebSocket協議第五章——數據幀(Data Framing)

      0                   1                   2                   3
      0 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 ...                |
     +---------------------------------------------------------------+

FIN: 1 bit。表示這是消息的最後一個片段。第一個片段也有可能是最後一個片段。

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中。Masking-Key中一般用於解碼“有效負載數據”。

Payload length: 7 bits, 7+16 bits, or 7+64 bits,以字節爲單位的“有效負載數據”長度。如果值爲0-125,那麼就表示負載數據的長度。如果是126,那麼接下來的2個bytes解釋爲16bit的無符號整形作爲負載數據的長度。如果是127,那麼接下來的8個bytes解釋爲一個64bit的無符號整形(最高位的bit必須爲0)作爲負載數據的長度。多字節長度量以網絡字節順序表示(譯註:應該是指大端序和小端序)。在所有的示例中,長度值必須使用最小字節數來進行編碼,例如:長度爲124字節的字符串不可用使用序列126,0,124進行編碼。有效負載長度是指“擴展數據”+“應用數據”的長度。“擴展數據”的長度可能爲0,那麼有效負載長度就是“應用數據”的長度。

Masking-Key: 0 or 4 bytes,所有從客戶端發往服務端的數據幀都已經與一個包含在這一幀中的32 bit的掩碼進行過了運算。爲什麼需要掩碼?爲了安全,但並不是爲了防止數據泄密,而是爲了防止早期版本的協議中存在的代理緩存污染攻擊(proxy cache poisoning attacks)等問題。

Payload data:有效負載數據,是指“擴展數據”和“應用數據”。

Extension data: x bytes:除非協商過擴展,否則“擴展數據”長度爲0 bytes。

Application data: y bytes。任意的“應用數據”,佔用“擴展數據”後面的剩餘所有字段。“應用數據”的長度等於有效負載長度減去“擴展應用”長度。

參考

即時通信網-Web端即時通訊技術盤點

掘金-黃Java-Websocket 協議 RFC 文檔(全中文翻譯)

原來你是這樣的 websocket

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章