網路基礎
JavaScript
WebSocket
參考資料:https://leesonhsu.blogspot.com/2018/07/socketwebsocketsocketio.html
WebSocket 是 HTML5 提供的一種網路傳輸協定,是瀏覽器(Client)與伺服器(Server)交換資料的方式之一。
與我們較為熟知的 HTTP 或 HTTPS 協定,同樣位於 OSI 模型的應用層,且基於傳輸層的 TCP 協定。其最大不同在於,WebSocket 協定只需連線一次,就能保持雙向溝通,不需重複發送 Request,因此回應更即時,進而提升 Web 通訊速度。
WebSocket 的建立是由瀏覽器透過 JavaScript 指令,發起一個 HTTP Request 來實現。請求網址會長這樣:
若經過 SSL 加密(WebSocket Secure),則加密連接網址會變成:
WebSocket 進行一次雙方握手過程,Client 端發送資訊:
Server 端回應資訊:
可參考 MDN 上提供的 WebSocket API 使用範例,建立簡單的 WebSocket 連線。
接下來會分幾個步驟來實作 WebSocket,其中又分 Server 和 Client 兩個面向進行:
那麼就開始吧!
這裡以 Node.js 為例,使用 Express 框架搭配 WebSocket 套件來建立環境。
關於如何使用 Express 來架設 Server,可參考過去寫的筆記:[week 17] 後端中階 - 使用 Node.js + Express 框架建立一個靜態網頁。
server.js
檔案,作為專案的進入點:即可輸入下方指令來運行 Server:
出現以下 log 代表 Server 正在監聽 8080 port:
處理完 Server 後,接下來要從 Client 端連結 WebSocket 服務。這裡需另起一個專案,包含 index.html 和 index.js 兩個檔案。
渲染後如下圖所示:
實際運行如下方所示 :
建立好 WebSocket 連結之後,就可以進行雙向溝通了!
Server 端分別能使用 send
發送訊息,以及透過監聽 message
事件接收來自 Client 的訊息:
同樣的,Client 端也能使用 send
送出訊息,以及透過 onmessage
接收 Server 端的訊息:
先前提到 WebSocket 常應用於即時聊天室等功能,也就是實現 Server 同時與多個 Client 連線。那該如何在 ClientA 傳送訊息給 Server 的同時,讓 ClientB 也接收到來自 Server 回傳的訊息呢?
這時就要仰賴「廣播功能」,首先透過 ws
提供的方法 clients
取得目前所有連線中的 Clients 資訊,再使用 forEach 迴圈送出訊息給每個 Client:
至於如何區分各個 Client,可參考這篇提供的方法:《webSocketServer node.js how to differentiate clients》,直接賦值 id 一個隨機變數。
或是參考 github 上的這篇討論 《unique identifier for each client request to websocket server》,直接取 request header 中的 'sec-websocket-key'
給每個 Client 新屬性 id:
總之目的是取得各個使用者獨一無二的識別證,透過這些識別證,又能夠對照到我們所熟悉的遊戲 ID 或是帳號。
經整理後的程式碼如下:
實際運行如下圖,完成具備廣播功能的即時聊天室!
在實際練習後,這裡整理一些常用的 WebSocket API:
new WebSocket()
:和 Server 建立 WebSocket 連線在建立 WebSocket 連線之後,即可透過 addEventListener()
監聽各種 Events,做出不同的對應方法,可參考 MDN 上的 Events:
同樣在建立 WebSocket 連線後,可使用以下 WebSocket 提供的方法進行互動:
Socket、Websocket、Socket.io 這三者都和網路即時通訊有關,名稱也有 87 像,但實際上是不同的東西,以下做簡單的整理介紹:
參考資料:https://leesonhsu.blogspot.com/2018/07/socketwebsocketsocketio.html
這次同樣是工作上接手新專案,需要研究 WebSocket 相關技術,於是又把過去一些網路基礎知識給複習一遍,每次都對網路協議多了一層認識。
對自己而言算是比較陌生的領域,即使大概知道功用是什麼,實際操作起來又是另一回事,但學習新知識果然還是很快樂,期許自己能夠早日上手。