1. 程式人生 > 程式設計 >從 0 到 1 的 websocket -- 概念篇

從 0 到 1 的 websocket -- 概念篇

技術篇 :Java 專案中的 WebSocket 實現

傳統方式的訊息推送

輪詢

客戶端定時向伺服器傳送 ajax 請求,伺服器收到請求後馬上返回訊息並關閉連線。

優點 :簡單粗暴,易於後端程式的編寫。

缺點 :輪詢需要頻繁向伺服器端傳送請求,詢問是否有資源需要更新,而這些請求大半是無用請求;此外,這種方式需要不斷建立 Http 連線,從而造成伺服器端與客戶端的資源浪費。

長輪詢

客戶端向伺服器傳送請求,伺服器收到請求後先按住不回覆,直到有新訊息時再返回響應並關閉連線;客戶端處理完響應資訊後再像伺服器傳送新的請求。

優點 :減少了很多不必要的 Http 請求次數,相比之下節約了資源。

缺點 :伺服器長時間保持連線會消耗資源,需要同時維護多個執行緒。而伺服器能承載的 TCP 連線數量是有限制的,這種輪詢很容易使連線數耗盡。

長連線

在頁面嵌入一個隱藏的 iframe,將這個隱藏 iframe 的 src 屬性設定為對一個長連線的請求或是採用 xhr(XMLHttpRequest 物件簡稱 XHR,通過其傳送的請求即 AJAX 請求)請求,服務端就能源源不斷地往客戶端輸入資料。

優點 :訊息即時到達,不需要傳送無用的請求。

缺點 :和長輪詢一樣,伺服器維護一個長連線會增加開銷,且需要處理高併發問題。

Flash Socket

在頁面嵌入一個使用了 Socket 類的 Flash 程式,JavaScript 通過呼叫此程式提供的 Socket 連線與伺服器端的 Socket 介面進行通訊,JavaScript 在收到服務端傳送的資訊後控制頁面的顯示。

優點 :與上述方式的偽隨機不同,這種方式能夠實現真正的即時通訊。

缺點 :客戶端必須安裝 Flash 外掛;該方式採用的並非 Http 協議,無法自動穿越防火牆。

真正的全雙工 -- WebSocket

websocket是什麼?

WebSocket 是 HTML5 開始提供的一種瀏覽器與伺服器進行全雙工通訊的網路技術,用以取代輪詢與長連線,使客戶端瀏覽器具備像 C/S 框架下桌面系統的即使通訊能力。

如何建立websocket連線?

1 . 首先由客戶端傳送握手請求,告訴伺服器將協議升級為 Websocket

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat,superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
複製程式碼

這一段用來告訴伺服器自己發起的是 Websocket 協議

Upgrade: websocket
Connection: Upgrade
複製程式碼

這一段用來對伺服器進行驗證,它由瀏覽器自主隨機生成

Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
複製程式碼

這一段用來告訴伺服器自己要的具體是什麼服務。其中,Sec-WebSocket-Protocol 是一個使用者定義的字串,用來區分同 URL 下,不同的服務所需要的協議

Sec-WebSocket-Protocol: chat,superchat
Sec-WebSocket-Version: 13
複製程式碼

2 . 然後伺服器會返回一個這樣的東西,表示已經收到請求,成功切換成 websocket 啦

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
複製程式碼

這一段用來告訴客戶端協議已經切換成功了

Upgrade: websocket
Connection: Upgrade
複製程式碼

這一段是經過伺服器確認,並且加密後的 Sec-WebSocket-Key,用來對驗證做出迴應

Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
複製程式碼

這一段表示最終使用的協議

Sec-WebSocket-Protocol: chat
複製程式碼

websocket的優勢是?

對於輪詢與長輪詢來說,客戶端都只能不斷地建立 Http 連線,然後被動等待伺服器的迴應。這種被動性使得伺服器端無法主動聯絡客戶端,即無法實現訊息的主動推送。

另一方面,不斷髮起請求的輪詢要求伺服器有很快的處理速度與資源,而保持連線不放的長輪詢則需要伺服器擁有足夠高的併發能力,來對多個客戶端進行同時接待。當訊息發生並不很頻繁時,這兩種方式都將造成巨大的資源浪費。

由此,websocket 出現了。再讓我們看一遍這個圖!

相比於傳統 Http 每次請求-應答需要每次重新建立連線的模式,WebSocket 是類似 Socket 的 TCP 長連線的通訊模式。一旦 WebSocket 連線建立之後,後續資料都以幀序列的形式傳輸。在客戶端斷開 WebSocket 連線或 Service 端中斷連線前,不需要客戶端和伺服器重新發起連線請求。在海量併發及客戶端與伺服器互動負載流量較大的情況下,極大地節省了網路頻寬資源的消耗,有明顯的效能優勢,且客戶端傳送和接收訊息是在同一個持久連線上發起的,實時性效果明顯

而與同樣能夠實現實時推送的 Http 長連線相比,WebSocket 主要擁有以下優勢 :

  • WebSocket 是真正的全雙工方式,建立連線後客戶端與伺服器端是完全平等的,可以相互主動請求;而 Http 長連線基於 Http,是傳統的客戶端對伺服器發起請求的模式。
  • 在 Http 長連線中,每次資料交換除了真正的資料部分外,伺服器和客戶端還需要交換大量的 Http Header,資訊交換效率很低;而 WebSocket 協議一旦通過第一個 request 與伺服器建立了 TCP 連線,之後的資料交換均不需要再次傳送 Http header,從而提高了資訊交換效率

雖然如此,WebSocket 依然存在一點侷限性。除了少數瀏覽器可能不支援該種協議外,基於多執行緒或多程式的伺服器同樣無法適用於 WebSocket,因為它旨在開啟連線,儘可能快地處理請求,然後關閉連線。任何實際的 WebSocket 伺服器端都需要一個非同步的實現。