WebSocket原理分析
Web應用的通信過程通常是客戶端通過瀏覽器發出一個請求,服務器端接收請求後進行處理並返回結果給客戶端,客戶端瀏覽器將信息呈現。這種機制對於信息變化不是特別頻繁的應用可以良好支撐,但對於實時要求高、海量並發的應用來說顯得捉襟見肘,尤其在當前業界移動互聯網蓬勃發展的趨勢下,高並發與用戶實時響應是Web應用經常面臨的問題,比如金融證券的實時信息、Web導航應用中的地理位置獲取、社交網絡的實時消息推送等。
傳統的請求-響應模式的Web開發在處理此類業務場景時,通常采用實時通訊方案。比如常見的輪詢方案,其原理簡單易懂,就是客戶端以一定的時間間隔頻繁請求的方式向服務器發送請求,來保持客戶端和服務器端的數據同步。其問題也很明顯:當客戶端以固定頻率向服務器端發送請求時,服務器端的數據可能並沒有更新,帶來很多無謂請求,浪費帶寬,效率低下。
基於Flash,AdobeFlash通過自己的Socket實現完成數據交換,再利用Flash暴露出相應的接口給JavaScript調用,從而達到實時傳輸目的。此方式比輪詢要高效,且因為Flash安裝率高,應用場景廣泛。然而,移動互聯網終端上Flash的支持並不好:IOS系統中無法支持Flash,Android雖然支持Flash但實際的使用效果差強人意,且對移動設備的硬件配置要求較高。2012年Adobe官方宣布不再支持Android4.1+系統,宣告了Flash在移動終端上的死亡。
傳統的Web模式在處理高並發及實時性需求的時候,會遇到難以逾越的瓶頸,需要一種高效節能的雙向通信機制來保證數據的實時傳輸。在此背景下,基於HTML5規範的、有Web TCP
用戶可以查閱HTML5規範,熟悉新的HTML協議規範及WebSocket支持。
一、Websocket機制
以下簡要介紹一下WebSocket的原理及運行機制。
WebSocket是HTML5的一種新的協議。它實現了瀏覽器與服務器全雙工通信
- WebSocket是一種雙向通信協議。在建立連接後,WebSocket服務器端和客戶端都能主動向對方發送或接收數據,就像Socket一樣;
- WebSocket需要像TCP一樣,先建立連接,連接成功後才能相互通信
傳統HTTP客戶端與服務器請求響應模式如下圖所示:
WebSocket模式客戶端與服務器請求響應模式如下圖:
上圖對比可以看出,相對於傳統HTTP每次請求-應答都需要客戶端與服務端建立連接的模式,WebSocket是類似Socket的TCP長連接通訊模式。一旦WebSocket連接建立後,後續數據都以幀序列的形式傳輸。在客戶端斷開WebSocket連接或Server端中斷連接前,不需要客戶端和服務端重新發起連接請求。在海量並發及客戶端與服務器交互負載流量大的情況下,極大的節省了網絡帶寬資源的消耗,有明顯的性能優勢,且客戶端發送和接受消息是在同一個持久連接上發起,實時性優勢明顯。
相比HTTP長連接,WebSocket有以下特點:
- 是真正的全雙工方式,建立連接後客戶端與服務器端是完全平等的,可以互相主動請求。而HTTP長連接基於HTTP,是傳統的客戶端對服務器發起請求的模式。
- HTTP長連接中,每次數據交換除了真正的數據部分外,服務器和客戶端還要大量交換HTTP header,信息交換效率很低。Websocket協議通過第一個request建立了TCP連接之後,之後交換的數據都不需要發送 HTTP header就能交換數據,這顯然和原有的HTTP協議有區別所以它需要對服務器和客戶端都進行升級才能實現(主流瀏覽器都已支持HTML5)。此外還有 multiplexing、不同的URL可以復用同一個WebSocket連接等功能。這些都是HTTP長連接不能做到的。
下面再通過客戶端和服務端交互的報文對比WebSocket通訊與傳統HTTP的不同點:
在客戶端,new WebSocket實例化一個新的WebSocket客戶端對象,請求類似 ws://yourdomain:port/path
的服務端WebSocket URL,客戶端WebSocket對象會自動解析並識別為WebSocket請求,並連接服務端端口,執行雙方握手過程,客戶端發送數據格式類似:
GET /webfin/websocket/ HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==
Origin: http://localhost:8080
Sec-WebSocket-Version: 13
可以看到,客戶端發起的WebSocket連接報文類似傳統HTTP報文,
Upgrade:websocket
參數值表明這是WebSocket類型請求,
Sec-WebSocket-Key
是WebSocket客戶端發送的一個 base64
編碼的密文,要求服務端必須返回一個對應加密的Sec-WebSocket-Accept
應答,否則客戶端會拋出Error during WebSocket handshake錯誤,並關閉連接。
服務端收到報文後返回的數據格式類似:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=
Sec-WebSocket-Accept
的值是服務端采用與客戶端一致的密鑰計算出來後返回客戶端的,
HTTP/1.1 101 Switching Protocols
表示服務端接受WebSocket協議的客戶端連接,
經過這樣的請求-響應處理後,兩端的WebSocket連接握手成功, 後續就可以進行TCP通訊了。
用戶可以查閱WebSocket協議棧了解WebSocket客戶端和服務端更詳細的交互數據格式。
在開發方面,WebSocket API 也十分簡單:只需要實例化 WebSocket,創建連接,然後服務端和客戶端就可以相互發送和響應消息。在WebSocket 實現及案例分析部分可以看到詳細的 WebSocket API 及代碼實現。
知乎有篇解釋,講的不錯:https://www.zhihu.com/question/20215561
WebSocket原理分析