我是web socket 彭于晏,我喂自己袋盐,请和我双工通信,亲密连接。
随着实时通信需求的增加,WebSocket 在前后端开发中的地位日益提升。本文将基于 Node.js + Express + React + Ant Design 实现一个完整的 WebSocket 聊天室 Demo,包含原生实现与优化建议,适合入门者快速掌握 WebSocket 的实际应用。

🧪 使用场景分析
WebSocket 是一种持久连接协议,允许服务端主动推送消息给客户端,适用于以下场景:
- 实时聊天 / 通知系统
- 实时协作编辑(如多人文档)
- 实时股票、币价、物流追踪
- 游戏对战通信
- 实时问答直播弹幕系统
🧠 一句话总结:
如果你有高频率数据更新 + 服务端推送需求,WebSocket 是更优解。
📦 技术栈简介
- 前端:React + TypeScript + Ant Design
- 后端:Node.js + Express + ws(WebSocket 原生库)
- 通信协议:WebSocket 标准协议(可升级为 socket.io)
🖥️ 后端实现(Node.js + ws)
安装依赖:
bash
复制编辑
npm install ws
后端代码结构:
arduino
cpp
复制编辑
├── app.js // Express 主入口
├── routes/
│ └── ws/index.js // WebSocket 服务初始化
1️⃣ WebSocket 处理逻辑(ws/index.js)
javascript
js
复制编辑
// ws/index.js
import { WebSocketServer } from "ws";
const clients = new Set();
export function initWebSocket(server) {
const wss = new WebSocketServer({ server });
wss.on("connection", (ws) => {
console.log("🟢 客户端连接 WebSocket");
clients.add(ws);
ws.on("message", (message) => {
console.log("📩 收到消息:", message.toString());
// 广播消息
clients.forEach((client) => {
if (client.readyState === ws.OPEN) {
client.send(message.toString());
client.send(`你好,${message.toString()}`);
}
});
});
ws.on("close", () => {
console.log("🔴 客户端断开");
clients.delete(ws);
});
});
console.log("✅ WebSocket 服务已启动");
}
2️⃣ 启动 Express + WebSocket(app.js)
javascript
js
复制编辑
import express from "express";
import http from "http";
import bodyParser from "body-parser";
import cors from "cors";
import { initWebSocket } from "./routes/ws/index.js";
const app = express();
const server = http.createServer(app);
app.use(cors());
app.use(bodyParser.json());
app.use(express.static("public"));
// 启用 WebSocket
initWebSocket(server);
server.listen(8088, () => {
console.log(`🚀 服务器启动成功:http://localhost:8088`);
});
💻 前端实现(React + Ant Design)
WebSocket 聊天室组件(WS.tsx
)
ini
tsx
复制编辑
import {
message as AntdMessage,
Button,
Card,
Input,
List,
Typography,
} from "antd";
import { useEffect, useRef, useState } from "react";
const { Text } = Typography;
const WS_URL = "ws://localhost:8088/ws";
export default function WS() {
const [msgList, setMsgList] = useState<string[]>([]);
const [inputMsg, setInputMsg] = useState("");
const wsRef = useRef<WebSocket | null>(null);
useEffect(() => {
const ws = new WebSocket(WS_URL);
wsRef.current = ws;
ws.onopen = () => AntdMessage.success("已连接 WebSocket");
ws.onmessage = (event) => {
setMsgList((prev) => [...prev, event.data]);
};
ws.onclose = () => AntdMessage.error("WebSocket 已断开");
return () => {
ws.close();
};
}, []);
const sendMessage = () => {
if (!inputMsg.trim()) return AntdMessage.warning("请输入消息内容");
if (wsRef.current?.readyState === WebSocket.OPEN) {
wsRef.current.send(inputMsg);
setInputMsg("");
} else {
AntdMessage.error("连接已断开,无法发送");
}
};
return (
<div style={{ padding: 48, maxWidth: 600, margin: "0 auto" }}>
<Card title="💬 WebSocket 聊天室 Demo" bordered>
<List
size="small"
dataSource={msgList}
renderItem={(item, index) => (
<List.Item key={index}>
<Text>{item}</Text>
</List.Item>
)}
style={{ maxHeight: 300, overflowY: "auto", marginBottom: 16 }}
/>
<Input.Group compact>
<Input
style={{ width: "calc(100% - 90px)" }}
value={inputMsg}
placeholder="请输入消息..."
onChange={(e) => setInputMsg(e.target.value)}
onPressEnter={sendMessage}
/>
<Button type="primary" onClick={sendMessage}>
发送
</Button>
</Input.Group>
</Card>
</div>
);
}


💡 小贴士:在浏览器开发者模式中,在NetWork 得 Socket中,可以实时查看两者客户端与服务端得消息传输内容。
⚙️ 进阶优化建议
虽然 ws
已可实现基本通信,但在实际生产中推荐使用更高级封装,如:
✅ 推荐使用 socket.io
的原因:
优点 | 说明 |
---|---|
自动重连 | 网络波动后可自动重连 |
自定义事件 | 支持 .emit('xxx') / .on('xxx') 事件系统 |
内建心跳机制 | 自动处理断线和心跳,连接更稳定 |
兼容性好 | 可兼容旧浏览器和 HTTP 长轮询兜底 |
社区强大 | 文档丰富、案例多、生态完善 |
可选替代库:
- socket.io-client
- reconnecting-websocket(更简单、仅用于自动重连)
💡 小贴士:靓仔,具体使用哪个第三方库看你使用场景,我这边上述展示代码,前端代码没有将ws得代码封装到utils,规范化的话请封装到utils使用。
🔚 总结
关键点 | 描述 |
---|---|
是否适合使用 WebSocket | 如果是高实时性需求(聊天、直播、推送),非常适合 |
生产环境推荐 | 封装库如 socket.io,提升开发体验与稳定性 |
不适用场景 | 数据更新不频繁、对实时性要求低的页面,建议仍用 HTTP 轮询或 RESTful |
💡 小贴士:使用场景可以跟后端沟通,后端吊毛说用就用呗,我管你这那得。
📎 最后
如果你觉得这篇文章对你有帮助,可以 点赞 + 收藏 + 关注 支持一下,我会持续更新更多【前后端实战 + 可运行 Demo】的技术分享 ❤️!
😩😩😩摸鱼真的好无聊,只能写写水文了。