簡介
WebSocket是一種在單個TCP連接上進行全雙工通訊的協議。WebSocket通信協議於2011年被IETF定爲標準RFC 6455,並由RFC7936補充規範。WebSocket API也被W3C定爲標準。
WebSocket使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在WebSocket API中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向數據傳輸。
出現背景
在websocket出現之前,實現服務器向客戶端推送信息,都是基於HTTP請求,實現技術有以下幾種:
輪詢方式:客戶端定時向服務端發送ajax請求,服務器接收到請求後馬上返回消息並關閉連接。
優點:後端程序編寫比較容易。
缺點:TCP的建立和關閉操作浪費時間和帶寬,請求中有大半是無用,浪費帶寬和服務器資源。
實例:適於小型應用。
長輪詢:客戶端向服務器發送Ajax請求,服務器接到請求後hold住連接,直到有新消息才返回響應信息並關閉連接,客戶端處理完響應信息後再向服務器發送新的請求。
優點:在無消息的情況下不會頻繁的請求,耗費資源小。
缺點:服務器hold連接會消耗資源,返回數據順序無保證,難於管理維護。
實例:WebQQ、Hi網頁版、Facebook IM。
長連接:在頁面裏嵌入一個隱蔵iframe,將這個隱蔵iframe的src屬性設爲對一個長連接的請求或是採用xhr請求,服務器端就能源源不斷地往客戶端輸入數據。
優點:消息即時到達,不發無用請求;管理起來也相對方便。
缺點:服務器維護一個長連接會增加開銷,當客戶端越來越多的時候,server壓力大!
實例:Gmail聊天
Flash Socket:在頁面中內嵌入一個使用了Socket類的 Flash 程序JavaScript通過調用此Flash程序提供的Socket接口與服務器端的Socket接口進行通信,JavaScript在收到服務器端傳送的信息後控制頁面的顯示。
優點:實現真正的即時通信,而不是僞即時。
缺點:客戶端必須安裝Flash插件,移動端支持不好,IOS系統中沒有flash的存在;非HTTP協議,無法自動穿越防火牆。
實例:網絡互動遊戲。
在這種情況下,HTML5定義了WebSocket協議,能更好的節省服務器資源和帶寬,並且能夠更實時地進行通訊。
Websocket使用ws或wss的統一資源標誌符,類似於HTTPS,其中wss表示在TLS之上的Websocket。如:
ws://example.com/wsapi wss://secure.example.com/
Websocket使用和 HTTP 相同的 TCP 端口,可以繞過大多數防火牆的限制。默認情況下,Websocket協議使用80端口;運行在TLS之上時,默認使用443端口。
優點
- 較少的控制開銷。在連接創建後,服務器和客戶端之間交換數據時,用於協議控制的數據包頭部相對較小。在不包含擴展的情況下,對於服務器到客戶端的內容,此頭部大小隻有2至10字節(和數據包長度有關);對於客戶端到服務器的內容,此頭部還需要加上額外的4字節的掩碼。相對於HTTP請求每次都要攜帶完整的頭部,此項開銷顯著減少了。
- 更強的實時性。由於協議是全雙工的,所以服務器可以隨時主動給客戶端下發數據。相對於HTTP請求需要等待客戶端發起請求服務端才能響應,延遲明顯更少;即使是和Comet等類似的長輪詢比較,其也能在短時間內更多次地傳遞數據。
- 保持連接狀態。於HTTP不同的是,Websocket需要先創建連接,這就使得其成爲一種有狀態的協議,之後通信時可以省略部分狀態信息。而HTTP請求可能需要在每個請求都攜帶狀態信息(如身份認證等)。
- 更好的二進制支持。Websocket定義了二進制幀,相對HTTP,可以更輕鬆地處理二進制內容。
- 可以支持擴展。Websocket定義了擴展,用戶可以擴展協議、實現部分自定義的子協議。如部分瀏覽器支持壓縮等。
握手協議
WebSocket 是獨立的、創建在 TCP 上的協議。
Websocket 通過 HTTP/1.1 協議的101狀態碼進行握手。
爲了創建Websocket連接,需要通過瀏覽器發出請求,之後服務器進行迴應,這個過程通常稱爲“握手”(handshaking),交互如下圖所示:
交互請求頭實例
一個典型的Websocket握手請求如下:
客戶端請求
GET / HTTP/1.1 Upgrade: websocket Connection: Upgrade Host: example.com Origin: http://example.com Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ== Sec-WebSocket-Version: 13
服務器迴應
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s= Sec-WebSocket-Location: ws://example.com/
字段說明
- Connection必須設置Upgrade,表示客戶端希望連接升級。
- Upgrade字段必須設置Websocket,表示希望升級到Websocket協議。
- Sec-WebSocket-Key是隨機的字符串,服務器端會用這些數據來構造出一個SHA-1的信息摘要。把“Sec-WebSocket-Key”加上一個特殊字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,然後計算SHA-1摘要,之後進行BASE-64編碼,將結果做爲“Sec-WebSocket-Accept”頭的值,返回給客戶端。如此操作,可以儘量避免普通HTTP請求被誤認爲Websocket協議。
- Sec-WebSocket-Version 表示支持的Websocket版本。RFC6455要求使用的版本是13,之前草案的版本均應當棄用。
- Origin字段是可選的,通常用來表示在瀏覽器中發起此Websocket連接所在的頁面,類似於Referer。但是,與Referer不同的是,Origin只包含了協議和主機名稱。
- 其他一些定義在HTTP協議中的字段,如Cookie等,也可以在Websocket中使用。
支持瀏覽器
實現websocket的協議,瀏覽器扮演着一個很重要的角色。所有最新的瀏覽器支持最新規範(RFC 6455)的WebSocket協議。一個詳細的測試報告列出了這些瀏覽器支持的Websocket版本。
瀏覽器支持現狀
協議 | 發佈日期 | IE | Firefox(個人電腦) | Firefox (Android) | Chrome(個人電腦,手機) | Safari(Mac, iOS) | Opera(個人電腦,手機) | Android瀏覽器 |
---|---|---|---|---|---|---|---|---|
hixie-75 | 2010年2月4日 | 4 | 5.0.0 | |||||
hixie-76 hybi-00 |
2010年5月10日, 2010年5月23日 |
4.0(已禁用) | 6 | 5.0.1 | 11.00(已禁用) | |||
7 hybi-07 | 2011年4月22日 | 6[4]1 | ||||||
8 hybi-10 | 2011年7月11日 | 7[5]1 | 7 | 14[6] | ||||
13 RFC 6455 | 2011年12月 | 10[7] | 11 | 11 | 16[8] | 6 | 12.10[9] | 4.4[10] |
參考資料
WebSocket
https://zh.wikipedia.org/wiki/WebSocket
java WebSocket開發入門WebSocket
https://www.jianshu.com/p/d79bf8174196
WebSocket 教程
http://www.ruanyifeng.com/blog/2017/05/websocket.html