websocket通訊原理

寫不好程式碼的格子襯衫發表於2019-04-25

http通訊只能一來一回,不能直接回包,於是出現了websocket實時通訊

背景

在websocket沒有出現之前,總會有一些需求,需要獲取資料,但是這些資料卻不知道哪個時間點才能獲取到,於是,大家使用了輪詢來解決伺服器推送的問題。

HTTP協議只能從客戶端發出請求,伺服器處理返回請求(這裡可以看下圖),但是伺服器不能主動給客戶端傳送請求,於是解決伺服器推送的問題,就只能靠輪詢了。

websocket通訊原理

輪詢分為兩種

  • 短輪詢:定時傳送http請求

  • 長輪詢:傳送請求直到收到訊息or超時後繼續傳送下一個請求

但是,輪詢並不能完美的解決伺服器推送的問題

  • 伺服器無法主動傳送資料
  • 輪詢實時性差
  • 輪詢浪費較多資源

概念

websocket的出現,就是為了解決伺服器推送的問題。

WebSocket是HTML5開始提供的一種在單個 TCP 連線上進行全雙工(通訊雙方既是接收方也是傳送方,兩端裝置可以同時傳送和接收資料)通訊的協議。

特性

  • 建立在TCP連結之上
  • 較少的控制開銷
  • 更強的實時性
  • 保持連線狀態
  • 可以傳送文字、二進位制資料
  • 沒有同源限制

連結過程

websocket的連結還是比較簡單的,只要進行一次握手,就可以進行後續的通訊了,這裡分為三步:

  1. http get請求將http請求升級為websocket請求
  2. 資料通訊
  3. 斷開連結(可由任一方中斷)

websocket通訊原理

握手協議

在第一步的時候進行了握手,這裡來看一下請求的詳情

// 請求
GET / HTTP/1.1
Upgrade: websocket // 升級為websocket協議
Connection: Upgrade 
Host: localhost:3000 // 請求host
Origin: http://binnie.com // 請求來源
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ== // 用於後續計算accept
Sec-WebSocket-Version: 13 // websocket版本號

複製程式碼
// 回包
HTTP/1.1 101 Switching Protocols // 101表示連結成功
Upgrade: websocket // 與請求對應
Connection: Upgrade
// 使用key計算得來,儘量避免普通HTTP請求被誤認為Websocket協議
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s= 
複製程式碼

幀格式

WebSocket協議使用幀(Frame)收發資料

客戶端傳送給服務端的幀必須通過4位元組的掩碼(Masking-key)加密,服務端收到訊息後,用掩碼對資料幀的Payload Data進行異或運算解碼得到資料,如果服務端收到未經掩碼加密的資料幀,則應該馬上關閉該WebSocket。

服務端發給客戶端的資料則不需要掩碼加密,客戶端如果收到了服務端的掩碼加密的資料,則也必須關閉它。

websocket通訊原理

上圖為websocket的幀格式,下面我們一個個來分析

這裡從左往右看,橫向為32位(bit)

  • FIN:最後的片段
  • RSV1-3:擴充定義
  • opcode:幀型別,其中控制幀:0x8 (Close), 0x9 (Ping), and 0xA (Pong),資料幀主要有:0x1 (Text), 0x2 (Binary)
  • MASK:資料是否掩碼
  • Payload len:負載長度
  • Extended payload length:擴充負載長度
  • Masking-key:掩碼
  • Playload Data:負載資料

所以,websocket傳遞資料時最小的請求頭為 FIN+RSV1-3+opcode+MASK+Payload len+Masking-key = 6 byte(位元組),剩下的就都是實際資料,相比於http頭部小得多。

相容性

websocket是很好的實時雙向通訊,不過相容性只到ie10,所以不支援websocket的瀏覽器就只能使用輪詢等方法來相容。

websocket通訊原理

寫在最後

由於低版本瀏覽器不支援websocket,需要使用輪詢來相容,於是出現了很多websocket庫,後面再分析websocket庫的實現。

相關文章