You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 16:03:10