1. 程式人生 > >WebSocket協議淺析

WebSocket協議淺析

HTTP協議的缺點

HTTP協議的缺點

  1. 單向請求:只能是客戶端發起,服務端處理並響應
  2. 請求/響應模式
  3. 無狀態協議
  4. 半雙工協議

這種單向請求的特點,註定瞭如果伺服器有連續的狀態變化,客戶端要獲知就非常麻煩。我們只能使用輪詢:每隔一段時候,就發出一個詢問,瞭解伺服器有沒有新的資訊。輪詢的效率低,非常浪費資源。WebSocket就可以解決這些問題。

WebSocket是什麼

WebSocket是HTML5新增的協議,目的是在瀏覽器和伺服器間建立一個不受限的全雙工通訊的通道。

其特點包括:

(1)建立在 TCP 協議之上,伺服器端的實現比較容易。

(2)與 HTTP 協議有著良好的相容性。預設埠也是80和443,並且握手階段採用 HTTP 協議,因此握手時不容易遮蔽,能通過各種 HTTP 代理伺服器。

(3)資料格式比較輕量,效能開銷小,通訊高效。

(4)可以傳送文字,也可以傳送二進位制資料。

(5)沒有同源限制,客戶端可以與任意伺服器通訊。

(6)協議識別符號是ws(如果加密,則為wss)。地址比如ws://example.com:80/some/path

協議概覽

協議分為兩部分:“握手” 和 “資料傳輸”。

握手協議

客戶端發出的握手資訊類似:

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

WebSocket連線必須由客戶端發起握手資訊。握手內容包括了 HTTP 升級請求和一些必選以及可選的頭欄位。握手的細節如下:

  • 握手必須是一個有效的 HTTP 請求
  • 請求的方法必須是 GET,並且 HTTP 的版本必須至少是 1.1
  • 請求的 Request-URI 部分可使相對路徑或者絕對路徑
  • 請求必須有一個 |Host| 頭欄位,它的值是 host 主機名稱加上 port 埠名稱(預設埠不必指明)
  • 請求必須有一個 |Upgrade| 頭欄位,它的值必須是 websocket 這個關鍵字
  • 請求必須有一個 |Connection| 頭欄位,它的值必須是 Upgrade 這個標記
  • 請求必須有一個 |Sec-WebSocket-Key| 頭欄位,它的值是一個噪音值。每個連線的噪音必須不同且隨機。
  • 如果連線來自瀏覽器客戶端,那麼 |Origin| 欄位就是必須的。如果連線不是來自於一個瀏覽器客戶端,那麼這個值就是可選的。這個值表示的是發起連線的程式碼在執行時所屬的源。關於源是由哪些部分組成的,見 RFC6454
  • 請求必須有一個 |Sec-WebSocket-Version| 頭欄位,它的值必須是 13
  • 請求可以有一個可選的頭欄位 |Sec-WebSocket-Protocol|。如果包含了這個頭欄位,它的值表示的是客戶端希望使用的子協議,按子協議的名稱使用逗號分隔。每個以逗號分隔的元素之間必須相互不重複。
  • 請求可以有一個可選的頭欄位 |Sec-WebSocket-Extensions|。如果包含了這個欄位,它的值表示的是客戶端希望使用的協議級別的擴充套件。
  • 請求可以包含其他可選的頭欄位,比如 cookies,或者認證相關的頭欄位,比如 |Authorization| 。

參考資料