
前言
這一篇是來簡單記錄一下如何建立一個簡易的 WebSocket 聊天室,而這邊主要會使用 Express 來當作範例,後續也會提供一個簡易的範例程式碼,讓大家可以參考。
什麼是 WebSocket?
WebSocket 是一個全新的網路傳輸協定,與 HTTP 協定最大不同在於 WebSocket 是屬於全雙工的的通訊,什麼意思呢?當我們畫面有任何操作行為時,都必須要先跟後端伺服器要求資料,舉例來講,假設畫面上我們要新增一筆資料時,我們就會跟後端請求新增資料的行為,新增完畢後再請求一次資料,這樣的行為就是屬於單向的通訊。
而 WebSocket 就跟原本 HTTP 單向通訊不同了,當 WebSocket 建立起交握後,接下來每一次的傳輸都是雙向的,也就是說,當我們新增一筆資料時,後端會主動推送資料給前端,而不需要前端再去請求一次,這樣的行為就是屬於雙向的通訊。
準備專案
基本上這邊我們為了方便練習以及起手,所以一率都會使用 Express 產生器來快速建立專案
1
| express --view=ejs express-websocket
|
接著我們會使用到一個套件,這個套件是用來處理 WebSocket 的,所以我們先安裝一下
到目前為止,我們專案的初步準備就完成了,接下來我們就來開始實作吧!
後端實作
首先一開始我們要先來實作後端的部分,目前我們專案的目錄結構如下
- bin
- node_modules
- public
- routes
- views
- app.js
- package.json
- package-lock.json
請你在當前根目錄下新增一個資料夾,名稱為 websocket,並在裡面新增一個檔案,名稱為 index.js,接下來呢?在官方 ws 文件中有提供範例程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) { ws.on('error', console.error);
ws.on('message', function message(data) { console.log('received: %s', data); });
ws.send('something'); });
|
那由於 Express 產生器主要是走 CommonJS 的方式,所以我們就將上面的程式碼改成 CommonJS 的方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws) { ws.on('error', console.error);
ws.on('message', function message(data) { console.log('received: %s', data); });
ws.send('something'); });
|
接下來打開 app.js,因為這是我們程式碼的進入點,所以我們要在這邊引入我們的 WebSocket 服務,並且啟動:
1 2 3 4
| const express = require('express'); ... require('./websocket');
|
那麼到目前為主,我們的後端就完成了,接下來我們就來實作前端的部分吧!
前端實作
那麼前端不像後端額外安裝套件,因為 WebSocket 是屬於瀏覽器的 API,所以我們是可以在前端直接使用的,而語法也很簡單,只需要這樣寫就可以了
1
| const ws = new WebSocket('ws://localhost:8080');
|
這邊有一個地方很有趣,也就是 ws://localhost:8080 這邊,以往我們在與後端做 AJAX 請求時都會是 https://example.com,而因為 WebSocket 兩者傳輸協定的不同,因此才會改用 ws://...,而這邊對應的 Port 主要是對應後端的 const wss = new WebSocketServer({ port: 8080 });。
接下來讓我們打開 views/index.ejs 檔案,你應該只會看到以下
1 2 3 4 5 6 7 8 9 10 11
| <!DOCTYPE html> <html> <head> <title><%= title %></title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <h1><%= title %></h1> <p>Welcome to <%= title %></p> </body> </html>
|
然後在底下增加一個 <script> 標籤,並貼入以下程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <!DOCTYPE html> <html> <head> <title><%= title %></title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <div id="content"> </div> <input type="text" id="input"> <button type="button" id="btn">送出</button>
<script> const ws = new WebSocket('ws://localhost:8080');
ws.addEventListener("open", (event) => { socket.send("Hello Server!"); });
ws.addEventListener("message", (event) => { console.log("Message from server ", event.data); }); </script> </body> </html>
|
這邊我們可以看到我們畫面上新增了 #content、input 跟 button 元素,接著你會發現我們從進入網頁那一刻,就已經開始與後端建立連線了,而當連線成功時,我們就會送出一個訊息給後端,並且監聽後端傳來的訊息,當後端傳來訊息時,我們就會在 console 中印出來。
接下來我們要來將前端改寫成一個簡單的聊天室,首先我們要先將 #btn 的 click 事件綁定,並且在點擊時,將 #input 的值送出去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const ws = new WebSocket('ws://localhost:8080');
ws.addEventListener("open", (event) => { socket.send("Hello Server!"); });
ws.addEventListener("message", (event) => { console.log("Message from server ", event.data); });
document.querySelector('#btn').addEventListener('click', () => { const value = document.querySelector('#input').value; ws.send(value); });
|
接下來你只要輸入內容並點一下按鈕就會觸發後端的顯示。
那接下來我們該如何實作成聊天室呢?由於這邊只是一個簡單示範,所以我們會將資料暫時儲存在後端記憶體內,以便我們可以在後端將資料傳給所有連線的使用者,所以這邊就要來修改一下後端的程式碼,這邊也不用擔心看不懂,我會增加註解說明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
const messages = [];
wss.on('connection', function connection(ws) { ws.on('error', console.error);
ws.on('message', function message(data) { messages.push(data.toString());
wss.clients.forEach((client) => { client.send(JSON.stringify(messages) || []); }); });
ws.send(JSON.stringify(messages) || []); });
|
接著就是來調整前端的程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| const ws = new WebSocket('ws://localhost:8080');
ws.addEventListener("open", (event) => { });
ws.addEventListener("message", (event) => { console.log("Message from server ", JSON.parse(event.data)); const content = document.querySelector('#content'); const data = JSON.parse(event.data); content.innerHTML = data.map((text) => `<p>${text}</p>`).join(''); });
document.querySelector('#btn').addEventListener('click', () => { const value = document.querySelector('#input').value; ws.send(value); });
|
那麼這樣子你就可以做出一個超級簡易的聊天室囉~

最後也提供一下這個範例的完整程式碼,有興趣的人可以參考看看。
結語
其實 WebSocket 用途還有很多,像是遊戲、即時通訊等等,這邊只是簡單的介紹一下,如果你有製作登入系統的話,就可以搭配上暱稱等等,所以其實 WebSocket 還滿有趣的。
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
Advertisement