Node.js用Socket.io搭建聊天系统客户端收不到消息仅重启服务端才生效
Socket.io服务端推送消息客户端无法接收解决方案
核心排查与修改点
- 版本匹配校验:客户端使用的是4.1.2版本的Socket.io,需确认服务端安装的
socket.io依赖大版本为4.x,2.x、3.x版本和4.x版本互不兼容,会导致消息收发异常。 - 用户映射存储结构错误:原代码使用数组
users存储业务用户ID和Socket ID的映射,业务ID多为非连续数字或字符串,作为数组索引会出现赋值/取值异常,需改为对象存储:var users = {}。 - 消息推送方法使用错误:
socket.to(socketId).emit()会排除当前连接的socket,若需直接向指定Socket ID推送消息,使用io.to(socketId).emit()更稳妥,避免上下文限制导致消息丢失。 - 增加跨域配置:Socket.io 4.x默认限制跨域,若前端页面地址和Socket服务地址不一致,需在服务端初始化时添加跨域配置。
- 添加日志排查:在映射存储、消息推送节点添加日志,确认目标Socket ID真实存在,避免因用户未上线、ID传错导致推送失败。
修改后服务端代码
var users = {}; const io = require('socket.io')(server, { pingInterval: 5000, pingTimeout: 5000, // 新增跨域配置,生产环境替换为前端实际域名 cors: { origin: "*", methods: ["GET", "POST"] } }); io.on('connection', (socket) => { console.log("User connected: ", socket.id); socket.on("user_connected", function (id) { users[id] = socket.id; console.log("当前用户映射:", users); io.emit("user_connected", id); }); socket.on('message', (msg) => { var socketId = users[msg.friendId]; console.log("目标Socket ID:", socketId); // 确认目标ID存在再推送 if (socketId) { io.to(socketId).emit('new_message', msg); } let chat = new ChatData({ user: msg.userId, friend: msg.friendId, message: msg.message }); chat.save().then(() => { console.log('message saved'); }).catch((err) => { console.log('error is ', err); }); }); });
优化后客户端代码(新增错误监听)
const socket = io("ws://localhost:3000"); // 新增连接错误监听,方便排查问题 socket.on('connect_error', (err) => { console.log('连接错误:', err); }); socket.on('connect', function() { console.log('连接成功,当前Socket ID:', socket.id); socket.emit("user_connected", userId); }); function sendMessage(message) { let msg = { userId: userId, friendId: friendId, message: message.trim() } socket.emit('message', msg); } socket.on('new_message', (msg) => { console.log('收到新消息:', msg) });
内容的提问来源于stack exchange,提问作者Sachin Kumar
相关产品推荐
相关产品推荐

