NodeJS Socket.io如何创建自定义房间实现向指定房间用户广播消息
Socket.io 自定义房间与定向推送实现方案
核心逻辑说明
Socket.io 中join()方法属于单个客户端连接的socket实例,只能在客户端和服务端建立连接后,对当前连接的socket对象调用,全局IO实例没有该方法;房间无需提前手动创建,调用join()时不存在会自动生成,所有成员离开后自动销毁。
步骤1:用户加入对应房间的实现
服务端修改Socket连接监听逻辑
修改你server.ts中的listenSockets方法,支持两种加入房间的场景:
private listenSockets (): void { console.log ('Listening Sockets'); this.io.on ('connection', client => { console.log ('Connected client', client.id, '当前所在房间:', client.rooms); // 场景1:连接建立时就通过auth参数携带分组ID(适合打开页面就已知用户分组的场景) const userChannelId = client.handshake.auth.channelId if (userChannelId) { client.join(userChannelId.toString()) // 统一转字符串避免类型不匹配 } // 场景2:登录后主动申请加入房间(适合登录后才拿到用户分组的场景) client.on('joinChannel', async (userId: string) => { // 校验用户身份后查询所属分组ID const user = await UserModel.findById(userId) if (user?.channel?._id) { const channelId = user.channel._id.toString() client.join(channelId) console.log(`用户${userId}成功加入分组房间${channelId}`) } }) // User disconnected disconnect (client); connect (client); }); }
客户端配合逻辑
两种场景对应客户端的两种实现:
- 场景1:初始化Socket连接时携带分组ID
// 客户端连接代码示例 import { io } from 'socket.io-client' const socket = io('你的服务端地址', { auth: { channelId: '当前用户的分组ID' // 从本地存储/登录态中取 } })
- 场景2:登录成功后主动触发加入房间事件
// 客户端登录成功后调用 socket.emit('joinChannel', '当前登录用户的ID')
步骤2:定向房间推送实现
你之前的推送写法是正确的,只要房间名和用户加入的房间名完全匹配即可:
import server from '../core/server'; // Socket broadcast, new information const __id = String (req.headers.id); const updatedData = await getNewData (__id); // 注意房间名要转成字符串,和用户加入时的名称完全一致 const targetRoom = updatedData._id.toString() Server.instance.io.in(targetRoom).emit ('data changed', updatedData);
常见注意事项
- 房间名必须保持类型完全一致,比如MongoDB返回的ObjectId要统一转成字符串再使用,避免数字/字符串/ObjectId类型不匹配导致推送不到
- 可以在
join()前增加权限校验,避免用户随意加入不属于自己的分组房间 - 如果需要查询某个房间下的所有连接,可以用
await Server.instance.io.in(房间ID).allSockets()获取连接ID集合
内容的提问来源于stack exchange,提问作者Alberto Siurob
相关产品推荐
相关产品推荐

