WebSocket 與 Socket.io

最近在作一個在線的聊天系統,我利用了 WebSocket 技術,具體說是websocket的庫socket.io。html

1. 什麼是 WebSocket

提到 WebSocket,我首先會想到 「及時通信」 和 「推送」 這類詞。在 WebSocket 之前,不少網站經過其餘方式來推送信息,下面咱們先看看之前的推送方式,這樣,有比較才能看出 WebSocket 的優點。程序員

1.1 (短)輪詢(Polling)

這種方式下,client 每隔一段時間都會向 server 發送 http 請求,服務器收到請求後,將最新的數據發回給 client。一開始必須經過提交表單的形式,這樣的後果就是傳輸不少冗餘的數據,浪費了帶寬。後來 Ajax 出現,減小了傳輸數據量。web

如圖所示,在 client 向 server 發送一個請求活動結束後,server 中的數據發生了改變,因此 client 向 server 發送的第二次請求中,server 會將最新的數據返回給 client。服務器

但這種方式也存在弊端。好比在某個時間段 server 沒有更新數據,但 client 仍然每隔一段時間發送請求來詢問,因此這段時間內的詢問都是無效的,這樣浪費了網絡帶寬。將發送請求的間隔時間加大會緩解這種浪費,但若是 server 更新數據很快時,這樣又不能知足數據的實時性。websocket

1.2 Comet

鑑於(短)輪詢的弊端,一種基於 HTTP 長鏈接的 「服務器推」 的技術被 hack 了出來,這種技術被命名爲 Comet。其與(短)輪詢主要區別就是,在輪詢方式下,要想取得數據,必須首先發送請求,在實時性要求較高的狀況下,只能增長向 server 請求的頻率;而 Comet 則不一樣,client 與 server 端保持一個長鏈接,只有數據發生改變時,server 才主動將數據推送給 client。Comet 又能夠被細分爲兩種實現方式,一種是長輪詢機制,一種是流技術。網絡

1.2.1 長輪詢(Long-polling)框架

client 向 server 發出請求,server 接收到請求後,server 並不必定當即發送迴應給 client,而是看數據是否更新,若是數據已經更新了的話,那就當即將數據返回給 client;但若是數據沒有更新,那就把這個請求保持住,等待有新的數據到來時,纔將數據返回給 client。socket

固然了,若是 server 的數據長時間沒有更新,一段時間後,請求便會超時,client 收到超時信息後,再當即發送一個新的請求給 server。網站

如圖所示,在長輪詢機制下,client 向 server 發送了請求後,server會等數據更新完纔會將數據返回,而不是像(短)輪詢同樣無論數據有沒有更新而後當即返回。編碼

這種方式也有弊端。當 server 向 client 發送數據後,必須等待下一次請求才能將新的數據發送出去,這樣 client 接收到新數據的間隔最短期即是 2 * RTT(往返時間),這樣便沒法應對 server 端數據更新頻率較快的狀況。

1.2.2 流技術(Http Streaming)

流技術基於 Iframe。Iframe 是 HTML 標記,這個標記的 src 屬性會保持對指定 server 的長鏈接請求,server 就能夠不斷地向 client 返回數據。

能夠看出,流技術與長輪詢的區別是長輪詢本質上仍是一種輪詢方式,只不過鏈接的時間有所增長,想要向 server 獲取新的數據,client 只能一遍遍的發送請求;而流技術是一直保持鏈接,不須要 client 請求,當數據發生改變時,server 自動的將數據發送給 client。

如圖所示,client 與 server 創建鏈接以後,便不會斷開。當數據發生變化,server 便將數據發送給 client。

但這種方式有一個明顯的不足之處,網頁會一直顯示未加載完成的狀態,雖然我沒有強迫症,但這點仍是難以忍受。

1.3 WebSocket

寫到如今,你們會發現,前人推出那麼多的解決方案,想要解決的惟一的問題即是怎麼讓 server 將最新的數據以最快的速度發送給 client。但 HTTP 是個懶惰的協議,server 只有收到請求才會作出迴應,不然什麼事都不幹。所以,爲了完全解決這個 server 主動向 client 發送數據的問題,W3C 在 HTML5 中提供了一種 client 與 server 間進行全雙工通信的網絡技術 WebSocket。WebSocket 是一個全新的、獨立的協議,基於 TCP 協議,與 HTTP 協議兼容卻不會融入 HTTP 協議,僅僅做爲 HTML5 的一部分。

那 WebSocket 與 HTTP 什麼關係呢?簡單來講,WebSocket 是一種協議,是一種與 HTTP 同等的網絡協議,二者都是應用層協議,都基於 TCP 協議。可是 WebSocket 是一種雙向通訊協議,在創建鏈接以後,WebSocket 的 server 與 client 都能主動向對方發送或接收數據。同時,WebSocket 在創建鏈接時須要藉助 HTTP 協議,鏈接創建好了以後 client 與 server 之間的雙向通訊就與 HTTP 無關了。

2. WebSocket 原理

相比於傳統 HTTP 的每次「請求-應答」都要 client 與 server 創建鏈接的模式,WebSocket 是一種長鏈接的模式。具體什麼意思呢?就是一旦 WebSocket 鏈接創建後,除非 client 或者 server 中有一端主動斷開鏈接,不然每次數據傳輸以前都不須要 HTTP 那樣請求數據。從上面的圖能夠看出,client 第一次須要與 server 創建鏈接,當 server 確認鏈接以後,二者便一直處於鏈接狀態。直到一方斷開鏈接,WebSocket 鏈接才斷開。

下面咱們從報文層面談一下 WebSocket 與 HTTP 的差別。

首先,client 發起 WebSocket 鏈接,報文相似於 HTTP,但主要有幾點不同的地方:

  • "Upgrade: websocket": 代表這是一個 WebSocket 類型請求,意在告訴 server 須要將通訊協議切換到 WebSocket

  • "Sec-WebSocket-Key:

    *
    ": 是 client 發送的一個 base64 編碼的密文,要求 server 必須返回一個對應加密的 "Sec-WebSocket-Accept" 應答,不然 client 會拋出 "Error during WebSocket handshake" 錯誤,並關閉鏈接

server 收到報文後,若是支持 WebSocket 協議,那麼就會將本身的通訊協議切換到 WebSocket,返回如下信息:

  • "HTTP/1.1 101 WebSocket Protocol Handshake":返回的狀態碼爲 101,表示贊成 client 的協議轉換請求

  • "Upgrade: websocket"

  • "Connection: Upgrade"

  • "Sec-WebSocket-Accept:

    *
    "

  • ...

以上都是利用 HTTP 協議完成的。這樣,通過「請求-相應」的過程, server 與 client 的 WebSocket 鏈接握手成功,後續即可以進行 TCP 通信了,也就沒有 HTTP 什麼事了。能夠查閱WebSocket 協議棧瞭解 WebSocket 的 client 與 server 更詳細的交互數據格式。

3. WebSocket 與 Socket.io

網絡應用中,兩個應用程序同時須要向對方發送消息的能力(即全雙工通訊),所利用到的技術就是 socket,其可以提供端對端的通訊。對於程序員而言,其須要在 A 端建立一個 socket 實例,併爲這個實例提供其所要鏈接的 B 端的 IP 地址和端口號,而在 B 端建立另外一個 socket 實例,而且綁定本地端口號來進行監聽。當 A 和 B 創建鏈接後,雙方就創建了一個端對端的 TCP 鏈接,從而能夠進行雙向通訊。

WebSocekt 是 HTML5 規範中的一部分,其借鑑了 socket 的思想,爲 client 和 server 之間提供了相似的雙向通訊機制。同時,WebSocket 又是一種新的應用層協議,包含一套標準的 API;而 socket 並非一個協議,而是一組接口,其主要方便你們直接使用更底層的協議(好比 TCP 或 UDP)

4. 什麼是 Socket.io

Socket.IO 是一個封裝了 Websocket、基於 Node 的 JavaScript 框架,包含 client 的 JavaScript 和 server 的 Node。其屏蔽了全部底層細節,讓頂層調用很是簡單。

另外,Socket.IO 還有一個很是重要的好處。其不只支持 WebSocket,還支持許多種輪詢機制以及其餘實時通訊方式,並封裝了通用的接口。這些方式包含 Adobe Flash Socket、Ajax 長輪詢、Ajax multipart streaming 、持久 Iframe、JSONP 輪詢等。換句話說,當 Socket.IO 檢測到當前環境不支持 WebSocket 時,可以自動地選擇最佳的方式來實現網絡的實時通訊。

相關文章
相關標籤/搜索