如何通过Socket.io从Node.js服务器向React前端特定用户组推送数据
实现Socket.io按站点分组推送消息的方案
核心思路
利用Socket.io内置的**房间(Room)**功能,将每个站点映射为一个独立房间。用户连接服务器时,根据其所属站点列表自动加入对应房间;服务器有IoT数据需要推送时,直接向目标站点的房间发送消息即可。用户若属于多个站点,会同时加入多个房间,自然能收到所有关联站点的推送。
具体实现步骤
1. 服务器端:用户连接时绑定站点房间
首先需要从可靠渠道(如数据库、用户认证信息)获取当前连接用户的所属站点列表,然后让用户Socket加入每个站点对应的房间。
const express = require('express'); const http = require('http'); const { Server } = require('socket.io'); const app = express(); const server = http.createServer(app); const io = new Server(server, { cors: { origin: "你的前端域名", // 生产环境替换为实际域名 methods: ["GET", "POST"] } }); // 模拟从数据库查询用户所属站点的函数(实际替换为业务逻辑) async function getUserAssociatedSites(userId) { // 示例:返回用户所属的站点数组 return ['abc', 'xyz']; } io.on('connection', async (socket) => { // 从握手信息中获取用户ID(实际可通过JWT解析、session等方式获取) const userId = socket.handshake.auth.userId; // 获取用户所属站点列表 const userSites = await getUserAssociatedSites(userId); // 让用户Socket加入每个站点对应的房间 userSites.forEach(site => { const roomName = `site_${site}`; // 用前缀避免房间名冲突 socket.join(roomName); console.log(`用户 ${userId} 加入站点房间 ${roomName}`); }); // 用户断开连接时,Socket.io会自动退出所有房间,无需手动处理 socket.on('disconnect', () => { console.log(`用户 ${userId} 断开连接`); }); }); // 站点数据推送函数:向指定站点的所有用户发送数据 function pushSiteIoTData(site, data) { const targetRoom = `site_${site}`; io.to(targetRoom).emit('site_iot_update', { siteId: site, data: data, timestamp: new Date().toISOString() }); } // 模拟IoT数据触发场景(实际替换为业务中的数据回调) setInterval(() => { // 给abc站点推送模拟的温湿度数据 pushSiteIoTData('abc', { temperature: Math.floor(Math.random() * 30 + 10), humidity: Math.floor(Math.random() * 60 + 20) }); // 给xyz站点推送模拟的设备状态数据 pushSiteIoTData('xyz', { deviceOnline: Math.random() > 0.2, powerConsumption: Math.random() * 100 + 50 }); }, 5000); server.listen(3000, () => { console.log('服务器运行在端口3000'); });
2. 前端:监听站点数据推送
前端只需建立Socket连接并监听指定事件,即可接收对应站点的推送数据。
// 建立Socket连接,传递用户ID(实际从登录态中获取) const socket = io('http://localhost:3000', { auth: { userId: 'user_12345' } }); // 监听站点数据更新事件 socket.on('site_iot_update', (payload) => { console.log(`站点 ${payload.siteId} 新数据:`, payload.data); // 这里更新仪表盘UI,渲染数据 });
关键注意事项
- 房间命名规范:用
site_前缀+站点名作为房间ID,避免与其他业务的房间冲突。 - 用户身份校验:必须通过后端可靠方式获取用户所属站点,禁止信任前端传递的站点列表,防止越权接收数据。
- 动态站点变更:如果用户所属站点发生修改(如后台调整权限),需要让用户重新连接,或在服务器主动调用
socket.leave(旧房间)和socket.join(新房间)更新房间关联。 - 性能优化:Socket.io的房间机制是轻量级的,即使单用户加入多个房间,也不会产生额外性能开销,适合IoT场景的近实时推送需求。
内容的提问来源于stack exchange,提问作者anonymous_33008899
相关产品推荐
相关产品推荐

