淺談即時通訊系統以及Socket.io、Socket、WebSocket 差異
Tags: webdev, webrtc, javascript, webscoket
Published: 2022-11-30 07:31:02

先前的專案中使用過 socket.io 實做聊天室功能，當初的概念只有 1. 事件驅動 2. HTTP之外的通訊協議 3. 即時互動，今天就來詳細了解 Websocket 與 HTTP 和網路是什麼關係、最後再來比較 socket.io 與 WebSocket 以及 socket 之間的差別。

在比較三者之間的差別之前必須要先理解為什麼我們不 HTTP 與 Websocket 之間的差別。
> # 從 HTTP 來比對即時通訊系統

傳統的瀏覽器以及 HTTP 早期只能夠從 client 端主動發出請求接著 server 端回應並回覆請求來實現資料互動，不過有許多像是監控、即時線上通訊、即時報價等情境，需要的是將後台發生的變化**主動、即時的**傳到瀏覽器端，而不是等待用戶手動更新頁面，也因此應運而生了許多方案。

 1. 輪詢 ( polling )：最簡單的方案。用戶端定期發送 AJAX 請求，伺服器再收到請求之後立刻回傳資料。雖然確保了資料的相對即時性也具有良好的瀏覽器相容性也很簡單。不過輪詢的頻率是最致命的缺點，舉例來說：當輪詢頻率太高時，就會產生大量無效請求; 過低時資料的即時性變差，同時，伺服器端壓力變大，進而浪費頻寬流量。

    function polling() {
      console.log("polling");
    }
    setInterval(shortPolling, 1000);

2. 長輪詢(long-polling) ：可想成輪詢的優化版本：用戶端透過 AJAX 發起請 求，伺服器端再接到請求後不馬上回傳，而是保持連接，等待資料更新。一旦有資料需要發送給用戶端時，伺服器端才將目標資料發送給用戶端，傳回請求。用戶端收到回應之後，馬上再發起一個新的請求給伺服器端，持續循環。

雖然能夠有效減少輪詢的次數以及大幅降低延遲，但伺服器需要保持大量的連結，也是會產生一定的消耗。

![圖一、[polling 與 long-polling 差異](https://codeburst.io/polling-vs-sse-vs-websocket-how-to-choose-the-right-one-1859e4e13bd9)](https://cdn-images-1.medium.com/max/2000/1*7bJdafKX_80jM6Di7au2vQ.png)

    function longPolling() {
      setTimeout(function() {
        console.log("Long Polling");
        longPolling();
      }, 1000);
    }
    longPolling();

3. Comet streaming ：此技術又被稱作 Forever iframe，需要我們動態載入一個隱藏的 iframe 標籤， iframe 標籤的 src 會指向請求的伺服器位址。同時 client 端會準備好一個處理資料的函式，在伺服器端透過 iframe 標和用戶端通訊時，伺服器端便會傳回 script 標籤的文字，用戶端會將其解析為 JavaScript 指令稿，並呼叫預先準備好的函數，將資料傳遞給 parant window，類似 JSONP 的實現原理，程式如下。

    <scritp>parant.getData("data from server")</script>

4. JAX multipart streaming：使用到了 HTTP 1.1 中的 multipart 特性：client 發送請求，server 保持連接，再利用 HTTP 1.1 的 chunked encoding 機制 (分段傳輸編碼 ) 將資料傳遞給用戶端，直到逾時或 client 端手動中斷才停止傳輸。

* 乍看之下與 WebSocket 功能似乎相同不過由於 HTTP 1.1 中的 multipart 特性並沒有被瀏覽器廣泛支援，此方法並不常見。

5. WebScoket：是從 HTML 5 開始提供的一種在瀏覽器與伺服器間進行全雙工通訊的網路技術。依靠此技術可以實現 client 端與 server 端的長連接，達到雙向即時通訊的效果。

![圖二、[WebSocket 與long-polling ](https://ably.com/blog/websockets-vs-long-polling)差異](https://cdn-images-1.medium.com/max/3162/1*1gjGSrruW2ipiVRbNPDB9A.png)
>  從 HTTP 與 WebSocket 的關係 ?

在[網路七層架構](https://medium.com/@sickmi14798/d040d8d581e6)( 日後再寫 )中，HTTP 與 WebSocket 都屬於第七層的應用層協定，且都是以 TCP 為基礎來傳輸資料。 WebSocket 依賴一種升級的 HTTP 進行一次驗證，驗證成功之後資料即可在 TCP 通道中進行傳輸了。

如此一來，**連接的發起端始終是 clinet 端**，不過一旦WebSocket 連接建立之後，不論是 clinet 端還是 server 端都可以向對方發送資料。

即使 WebSocket 強大，還是錯過了瀏覽器為 HTTP 提供的一些服務，這些服務就需要開發者自行實現，因此 WebSocket 暫時還無法取代 HTTP 。
> # Socket.io、Socket、WebSocket 差異

講了這麼多終於談到今天的主題了，在進入主題之前TCP/IP 的四個層級介紹可以更了解三者之間的關係。

TCP/IP 的四個層級介紹：

* 應用層 (Application Layer)：網路模型的最上層，也是想要利用網路傳輸資料的程式，能夠直接碰觸到的層級。EX： telnet、FTP、WWW、Email、DNS、socket.io、HTTP、WebSocket、engine.io

* 傳輸層 (Transport Layer)：此層對應用層傳送過來的資料進行處理，建立2台電腦之間可靠的傳輸，在此層常見的2種協定為TCP與UDP。

* 網路層 (IP Network Layer)：網路層能夠提供實體介面網路卡一個邏輯上的位置，也就是我們常聽到的IP位址。

* 鏈接層 (Network Access Layer)：位於整個網路架構的最底層，負責制定資料傳輸的「實體」規格 ，EX：乙太網路的規格等。

![圖三、四層架構](https://cdn-images-1.medium.com/max/2000/1*w2_5VJ3fSyydVd_0CF9Daw.png)

## Socket 是甚麼 ? 它在哪裡 ?

Socket是應用層與TCP/IP協議通信的中間軟體抽象層，它是**一組介面 ( **Socket Interface **)**。

在設計模式中， Socket其實就是一個門面模式，它**把複雜的TCP/IP協議隱藏在Socket介面後面，**對用戶來說，一組簡單的介面就是全部，讓Socket去組織數據。

![圖三、socket 位於*傳輸層跟應用層之間*](https://cdn-images-1.medium.com/max/2000/1*g_U7H2ZOnZtcdnW4P_23Vw.png)

介紹完 socket 後相信讀者對於應用層中的 Socket.io 與 Websocket 又更好奇了

## WebSocket

WebSocket 顧名思義，就是為了提升 web 通訊速度而被創造出來的一種**「協議」，**它的原理是在瀏覽器底層以剛剛提到的「socket」當作**通訊介面**，通訊協議才是採用它自身的「Websocket協議」。

可以想成**協議與介面**都裝在瀏覽器上，因此只要瀏覽器支援，就可以使用這個協議透過web來跟伺服器做溝通。

### WebSocket 與 HTTP 的關係

我們都清楚要和 server 溝通需要通過 HandShaking ，Websocket 也不例外，而第一次 HandShaking 則是使用**「HTTP協議」**接下來 HTTP協議就不會再用到囉，而是使用 Websocket 協議。

![](https://cdn-images-1.medium.com/max/2000/1*jRFxDJr88he3ZXNcJQLRMw.png)

## socket.io && engin.io

那大家最熟悉的 socket.io 又是甚麼呢 ? 解決了甚麼問題呢 ?

與 WebScoket 一樣 socket.io 也是為了解決 web 即時通訊而誕生的，不一樣的是 **socket.io 是一個框架而不是協議。**
>  上面有提到要在瀏覽器有支援的前提之下才能使用 WebSocket ，那如果瀏覽器不支援，而程式裡使用了 WebSocket 的技術時怎麼辦呢 ??

socket.io 解決了這個問題，在大部分情況之下 WebSocket 與 socket.io都是使用 WebSocket 協議做即時的通訊，不過當遇到上述情境時，**socket.io會改選擇使用傳統的 long-polling ( 長輪詢 ) 方式運作**。

沒錯!! 就是一開始介紹的那種即時通訊方式。

不過 socket.io 僅僅是在上層做一些介面封裝，真正連線的角色是 **engin.io** 舉凡通訊相關，連接等等，都是engine.io在實現。

小結：講了這麼多，最後用個表格來簡單區分 WebSocket 與 Socket.io 的主要差別。

![](https://cdn-images-1.medium.com/max/2000/1*-3z0fIMFW3MG7GCtWhB3KQ.png)