WebSocket協議淺析
阿新 • • 發佈:2018-11-03
HTTP協議的缺點
- 單向請求:只能是客戶端發起,服務端處理並響應
- 請求/響應模式
- 無狀態協議
- 半雙工協議
這種單向請求的特點,註定瞭如果伺服器有連續的狀態變化,客戶端要獲知就非常麻煩。我們只能使用輪詢:每隔一段時候,就發出一個詢問,瞭解伺服器有沒有新的資訊。輪詢的效率低,非常浪費資源。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| 。