
傳統 HTTP 就像打電話給客服——你問一個問題、對方回答、掛斷。WebSocket 是讓你跟伺服器之間「保持通話不掛斷」的技術。
先講結論
WebSocket 提供全雙工通訊——伺服器可以主動推送資料給客戶端,不需要客戶端先發請求。適合即時聊天、股票行情、多人遊戲這類需要「一有新資料馬上送」的場景。不是所有應用都需要 WebSocket,大部分 CRUD 用 REST 就夠了。
為什麼 HTTP 不夠用?
HTTP 是「請求-回應」模式:客戶端問、伺服器答、結束。伺服器沒辦法主動找客戶端說話。
那如果要做即時通知呢?傳統有兩種做法:
- 輪詢(Polling):每隔幾秒發一次請求問「有新消息嗎?」——99% 的請求回來都是「沒有」。浪費頻寬又浪費 CPU。
就像每五分鐘問一次「到了嗎」的副駕。 - 長輪詢(Long Polling):發請求後伺服器不馬上回應,等到有新資料才回——比輪詢好,但每次回應完又要重新建立連線。
WebSocket 一勞永逸:建立一次連線,之後雙方隨時互發訊息。
怎麼建立連線
WebSocket 從一個 HTTP 請求開始,然後「升級」成 WebSocket 協定:
客戶端:「嘿,我想升級成 WebSocket」
GET /chat HTTP/1.1
Upgrade: websocket
Connection: Upgrade
伺服器:「好,升級成功」
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
握手完成後,連線就從 HTTP 變成 WebSocket 了。之後的通訊不再是 HTTP,而是更輕量的 WebSocket frame。
前端怎麼用
瀏覽器原生就支援 WebSocket API,不用裝任何套件:
const socket = new WebSocket('wss://example.com/socket');
socket.onopen = () => {
console.log('已連線');
socket.send('Hello Server!');
};
socket.onmessage = (event) => {
console.log('收到:', event.data);
};
socket.onclose = () => console.log('連線已關閉');
socket.onerror = (error) => console.error('錯誤:', error);就這樣。四個事件處理器:onopen、onmessage、onclose、onerror。比你想像的簡單很多。
動手做:5 分鐘即時聊天室
看概念不如直接寫一個。
Server(Node.js)
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
const clients = new Set();
wss.on('connection', (ws) => {
clients.add(ws);
ws.on('message', (message) => {
const data = JSON.parse(message);
// 廣播給所有人
clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
user: data.user,
text: data.text,
time: new Date().toLocaleTimeString()
}));
}
});
});
ws.on('close', () => clients.delete(ws));
});Client(純 HTML)
<div id="messages" style="height:300px;overflow-y:auto;border:1px solid #ccc;padding:10px"></div>
<input id="name" placeholder="你的名字" />
<input id="input" placeholder="輸入訊息..." />
<button onclick="send()">送出</button>
<script>
const ws = new WebSocket('ws://localhost:8080');
ws.onmessage = (e) => {
const data = JSON.parse(e.data);
messages.innerHTML += `<p><b>${data.user}</b> [${data.time}]: ${data.text}</p>`;
};
function send() {
const text = input.value;
if (text) {
ws.send(JSON.stringify({ user: name.value || '匿名', text }));
input.value = '';
}
}
input.addEventListener('keypress', (e) => { if (e.key === 'Enter') send(); });
</script>mkdir ws-chat && cd ws-chat && npm init -y && npm i ws
# 建立 server.js,啟動 node server.js
# 開兩個瀏覽器分頁,打開 index.html,即時聊天!這個 demo 展示了 WebSocket 的三個核心特性:全雙工(Server 主動 push)、持久連線(不用每次重新握手)、廣播(一人發訊息,所有人收到)。
WebSocket vs HTTP
| HTTP | WebSocket | |
|---|---|---|
| 連線 | 短連線(請求-回應) | 長連線(持續保持) |
| 方向 | 單向(客戶端發起) | 雙向 |
| 延遲 | 較高 | 極低 |
| 適合 | 一般 CRUD | 即時互動 |
正式產品還需要什麼
Demo 能跑,但離正式產品還差:心跳機制(ping/pong 防 timeout)、自動重連(斷線後重連)、房間機制(不是所有人都收到)、認證(連線時驗 token)。
實務上大多會用 Socket.IO——它幫你處理好自動重連、房間、fallback 到 long polling 等雜事。或者如果你只需要伺服器單向推送,Server-Sent Events(SSE) 更簡單。
不是所有東西都需要即時——但需要即時的時候,HTTP 真的救不了你。