開始使用
在本指南中,我們將建立一個基本的聊天應用程式。它幾乎不需要任何 Node.JS 或 Socket.IO 的基本先備知識,因此非常適合所有知識程度的使用者。
簡介
使用流行的網頁應用程式堆疊(例如 LAMP (PHP))撰寫聊天應用程式通常非常困難。它涉及輪詢伺服器以取得變更,追蹤時間戳記,而且速度比預期慢很多。
Socket 傳統上是大多數即時聊天系統建構的解決方案,它提供用戶端與伺服器之間的雙向通訊管道。
這表示伺服器可以將訊息「推播」給用戶端。每當您撰寫聊天訊息時,其概念是伺服器會取得該訊息並將其推播給所有其他已連線的用戶端。
網頁架構
第一個目標是設定一個簡單的 HTML 網頁,用於提供表單和訊息清單。我們將使用 Node.JS 網頁架構 express
來達成此目的。請確定已安裝 Node.JS。
首先,讓我們建立一個描述專案的 package.json
清單檔。我建議您將其放在專用的空目錄中(我將我的目錄命名為 chat-example
)。
{
"name": "socket-chat-example",
"version": "0.0.1",
"description": "my first socket.io app",
"dependencies": {}
}
「名稱」屬性必須是唯一的,您不能使用「socket.io」或「express」等值,因為 npm 會在安裝相依項時抱怨。
現在,為了使用我們需要的項目輕鬆填入 dependencies
屬性,我們將使用 npm install
npm install express@4
安裝後,我們可以建立一個 index.js
檔,用於設定我們的應用程式。
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
app.get('/', (req, res) => {
res.send('<h1>Hello world</h1>');
});
server.listen(3000, () => {
console.log('listening on *:3000');
});
這表示
- Express 將
app
初始化為函數處理常式,您可以提供給 HTTP 伺服器 (如第 4 行所示)。 - 我們定義路由處理常式
/
,當我們進入網站首頁時會呼叫此處理常式。 - 我們讓 http 伺服器在埠 3000 上監聽。
如果您執行 node index.js
,您應該會看到下列內容

如果您將瀏覽器指向 http://localhost:3000

提供 HTML
到目前為止,在 index.js
中,我們呼叫 res.send
並傳遞給它一個 HTML 字串。如果我們只將整個應用程式的 HTML 放置在那裡,我們的程式碼看起來會非常混亂,因此我們將建立一個 index.html
檔案並提供該檔案。
讓我們重構我們的路由處理常式,改用 sendFile
。
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
將下列內容放入您的 index.html
檔案
<!DOCTYPE html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
#form { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; position: fixed; bottom: 0; left: 0; right: 0; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }
#input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; }
#input:focus { outline: none; }
#form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages > li { padding: 0.5rem 1rem; }
#messages > li:nth-child(odd) { background: #efefef; }
</style>
</head>
<body>
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" /><button>Send</button>
</form>
</body>
</html>
如果您重新啟動程序 (按 Control+C 並再次執行 node index.js
) 並重新整理頁面,它應該看起來像這樣

整合 Socket.IO
Socket.IO 由兩部分組成
- 與 Node.JS HTTP 伺服器整合 (或安裝在該伺服器上) 的伺服器 socket.io
- 載入瀏覽器端的用戶端程式庫 socket.io-client
在開發期間,socket.io
會自動為我們提供用戶端,正如我們將看到的,因此現在我們只需要安裝一個模組
npm install socket.io
這將安裝模組並將相依關係新增至 package.json
。現在讓我們編輯 index.js
以新增它
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
console.log('a user connected');
});
server.listen(3000, () => {
console.log('listening on *:3000');
});
請注意,我透過傳遞 server
(HTTP 伺服器) 物件初始化 socket.io
的新執行個體。然後我監聽 connection
事件以接收傳入的 socket 並將其記錄到主控台。
現在在 index.html
中,在 </body>
(結束 body 標籤) 之前新增下列程式碼片段
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
</script>
這只需要載入 socket.io-client
,它會公開一個 io
全域變數 (和端點 GET /socket.io/socket.io.js
),然後連線。
如果您想使用用戶端端 JS 檔案的本機版本,您可以在 node_modules/socket.io/client-dist/socket.io.js
找到它。
您也可以使用 CDN,而不是本機檔案 (例如 <script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>
)。
請注意,當我呼叫 io()
時,我沒有指定任何 URL,因為它預設會嘗試連線到提供頁面的主機。
如果您現在重新啟動程序(按 Control+C 並再次執行 node index.js
),然後重新整理網頁,您應該會看到主控台列印「使用者已連線」。
嘗試開啟多個分頁,您將會看到多則訊息。

每個 Socket 也會觸發一個特殊的 disconnect
事件
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
});
然後,如果您重新整理分頁多次,您可以在動作中看到它。

發射事件
Socket.IO 背後的主要概念是,您可以傳送和接收任何您想要的事件,以及任何您想要的資料。任何可以編碼為 JSON 的物件都可以,而且二進位資料也受支援。
讓我們這樣做,當使用者輸入訊息時,伺服器會將它作為 chat message
事件接收。index.html
中的 script
區段現在應該如下所示
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
var form = document.getElementById('form');
var input = document.getElementById('input');
form.addEventListener('submit', function(e) {
e.preventDefault();
if (input.value) {
socket.emit('chat message', input.value);
input.value = '';
}
});
</script>
而在 index.js
中,我們列印出 chat message
事件
io.on('connection', (socket) => {
socket.on('chat message', (msg) => {
console.log('message: ' + msg);
});
});
結果應該像以下影片
廣播
我們的下一個目標是從伺服器發射事件到其他使用者。
為了將事件傳送給所有人,Socket.IO 提供了 io.emit()
方法。
io.emit('some event', { someProperty: 'some value', otherProperty: 'other value' }); // This will emit the event to all connected sockets
如果您想要將訊息傳送給所有人,除了某個發射 Socket,我們有 broadcast
旗標,可以從該 Socket 發射
io.on('connection', (socket) => {
socket.broadcast.emit('hi');
});
在這種情況下,為了簡單起見,我們會將訊息傳送給所有人,包括寄件者。
io.on('connection', (socket) => {
socket.on('chat message', (msg) => {
io.emit('chat message', msg);
});
});
而在用戶端,當我們擷取 聊天訊息
事件時,我們會將其包含在頁面中。總計用戶端 JavaScript 程式碼現在等於
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
var messages = document.getElementById('messages');
var form = document.getElementById('form');
var input = document.getElementById('input');
form.addEventListener('submit', function(e) {
e.preventDefault();
if (input.value) {
socket.emit('chat message', input.value);
input.value = '';
}
});
socket.on('chat message', function(msg) {
var item = document.createElement('li');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
</script>
這樣就完成了我們的聊天應用程式,大約 20 行程式碼!它看起來像這樣
作業
以下是改善應用程式的部分構想
- 當有人連線或斷線時,廣播訊息給已連線的使用者。
- 加入對暱稱的支援。
- 不要將相同的訊息傳送給傳送訊息的使用者。相反地,在他們按下 Enter 鍵後,直接附加訊息。
- 加入「{使用者} 正在輸入」功能。
- 顯示誰在線上。
- 加入私人訊息傳送。
- 分享你的改善成果!
取得此範例
你可以在 GitHub 在此處找到它。
git clone https://github.com/socketio/chat-example.git