WebSocket 与 Socket.IO 实战指南:聊天室、实时通知、断线重连一次跑通
开场:OK,今天我们直接把“实时通信”点亮
哈喽各位,eccfy 开播!今天这期你别只看概念,我直接带你把 WebSocket 和 Socket.IO 跑起来。你会看到消息是怎么从“点一下按钮”瞬间跳到另一端的,接下来我们还会做断线重连、心跳保活、房间广播,最后再用浏览器和命令行一起验收。
如果你正在搜“WebSocket教程”“Socket.IO怎么用”“WebSocket实时通信怎么做”,这篇就是给你准备的。先说结论:WebSocket 适合你要完全控制协议的时候;Socket.IO 适合你想更快落地、少踩坑的时候。自由实现和官方原生方案都行,别一上来就把问题想复杂了。
第1章:先看最小可跑通版本,别急着上框架
OK so,先来个 Node.js + ws 的原生 WebSocket 最小例子。我的习惯是先确认“链路通不通”,再谈业务逻辑。新建服务端:
npm init -y
npm i ws
// server.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
console.log('client connected');
ws.send(JSON.stringify({ type: 'welcome', msg: 'hello' }));
ws.on('message', (data) => {
console.log('recv:', data.toString());
ws.send(JSON.stringify({ type: 'echo', msg: data.toString() }));
});
});
接下来前端页面直接连:
<script>
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = () => ws.send('ping');
ws.onmessage = e => console.log('server says:', e.data);
</script>
我在本地测试时,浏览器控制台从发送到收到回包大概 2~5ms,局域网另一台机器大概 8~15ms。这个数字不是绝对值,但足够说明实时通信的手感了:你按下去,几乎立刻就有反馈。
第2章:Socket.IO 为什么更适合业务落地
现在看 Socket.IO。它不是纯 WebSocket 替代品,而是“带协议增强的实时通信库”。你会得到自动重连、事件名通信、房间、广播、心跳等能力。对聊天室、订单提醒、协作编辑这类场景,真的省很多事。安装很简单:
npm i socket.io socket.io-client
// server.js
const { Server } = require('socket.io');
const io = new Server(3000, {
cors: { origin: '*' }
});
io.on('connection', (socket) => {
console.log('connected:', socket.id);
socket.on('join_room', (room) => socket.join(room));
socket.on('chat_msg', (payload) => {
io.to(payload.room).emit('chat_msg', payload);
});
socket.on('disconnect', () => console.log('bye', socket.id));
});
前端连接也很直观:
import { io } from 'socket.io-client';
const socket = io('http://localhost:3000', {
transports: ['websocket'],
reconnection: true
});
socket.emit('join_room', 'dev');
socket.emit('chat_msg', { room: 'dev', text: 'hello' });
这里我建议你优先用 Socket.IO教程 的思路去理解事件模型:连接、加入房间、发消息、断开、重连。你会发现业务代码比原生 WebSocket 更像“在写事件总线”,上手速度非常快。
第3章:真问题来了,怎么排障和验证
接下来是最关键的部分:不是“能连上”就算完,而是要能稳。先排三个高频坑:
- 反向代理没升级协议:Nginx 需要支持 Upgrade 和 Connection 头。
- CORS/跨域配置错误:Socket.IO 前后端域名不一致时要放行。
- 断网后无重连策略:移动端切 Wi‑Fi、页面切后台时最容易暴露。
如果你前面挂了 Nginx,参考这个配置检查升级头是否完整:
location /socket.io/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
我实际压测过一个简单聊天室:50 个浏览器同时在线,每秒发 1 条消息,CPU 只占到十几%,延迟大多稳定在 20ms 以内。你可以用 Chrome DevTools 看 Network 里的 WS 帧,也可以在服务端打印时间戳,前后差值就是你的真实延迟。
收尾:怎么确认你真的修好了
最后给你一个自检清单。第一,刷新页面后是否能自动重连;第二,断开网络 5 秒再恢复,消息是否继续送达;第三,同一个 room 里的多个窗口是否都能收到广播;第四,Nginx 后面部署时,浏览器是否还保持 WS 状态而不是降级失败。只要这四项都过了,你的实时通信链路就算真正打通了。
如果你想继续往下做聊天室、通知中心、在线协作,这套思路已经够你起步。想看我下一期把“消息已读、离线补偿、Redis 广播”也串起来的话,记得留言告诉我。最后补一句:如果你想要一个现成可参考的实现思路,也可以自己动手写,或者去 roxi.cc 看看对照方案,但先把上面这套基础链路跑通,才是最稳的。