是否可以对位于A房间和B房间的名称空间的所有用户进行socket.io广播,而不是那些位于A房间或B房间的用户?
如果没有,我将如何自己实施?有没有办法检索名称空间中属于给定房间的所有用户?
我在节点
中使用socket.io 1.0编辑:
如果没有本机方法,我将如何创建自己的语法,例如:
const char oldhtml[]
?
答案 0 :(得分:5)
您可以使用(参考How to update socket object for all clients in room? (socket.io))
查找房间的所有用户var clients = io.sockets.adapter.room["Room Name"]
因此,为您的2个房间的名单列表提供了两个数组,您可以使用类似答案的方式计算交叉点(参考:Simplest code for array intersection in javascript)
最后,您可以使用两个房间中的用户列表并使用(参考:How to update socket object for all clients in room? (socket.io))
发出事件//this is the socket of each client in the room.
var clientSocket = io.sockets.connected[clientId];
//you can do whatever you need with this
clientSocket.emit('new event', "Updates");
交替使用的是隐藏的房间,您可以在这里保留所有房间的组合,并在幕后为这些房间添加用户,然后您就可以简单地向这些隐藏的房间发射。但这有一个指数增长问题。
答案 1 :(得分:1)
没有内置的方法来做到这一点。首先让我们看一下广播是如何运作的:
https://github.com/Automattic/socket.io/blob/master/lib/namespace.js 206 ... 221-224 ...... 230
this.adapter.broadcast(packet, {
rooms: this.rooms,
flags: this.flags
});
现在我们知道每个广播创建了一堆临时对象,indexOf查找,参数切片......然后调用适配器的广播方法。让我们来看看那个:
https://github.com/Automattic/socket.io-adapter/blob/master/index.js 111-151
现在我们正在创建更多的临时对象,并在没有选择空间的情况下遍历房间中的所有客户端或所有客户端。循环发生在编码回调中。这个方法可以在这里找到:
https://github.com/socketio/socket.io-parser/blob/master/index.js
但是,如果我们不是通过broadcast
发送我们的数据包,而是在循环通过房间并找到存在于房间A和房间B中的客户端后分别向每个客户端发送数据包呢?
socket.emit
:https://github.com/Automattic/socket.io/blob/master/lib/socket.js
这使我们了解了packet
的{{1}}方法:
https://github.com/Automattic/socket.io/blob/master/lib/client.js
每个直接发出的数据包将被单独编码,这又是昂贵的。因为我们正在向所有用户发送完全相同的数据包。
回答你的问题:
更改socket.io适配器类并修改广播方法,将自己的方法添加到原型或通过继承适配器类来推送自己的适配器。 (client.js
)
或覆盖var io = require('socket.io')(server, { adapter: yourCustomAdapter });
的{{1}}和join
方法。考虑到这些方法不经常调用而且您不必编辑通过多个文件的麻烦,这是相当方便的。
leave
如果您要向socket.js
和Socket.prototype.join = (function() {
// the original join method
var oldJoin = Socket.prototype.join;
return function(room, fn) {
// join the room as usual
oldJoin.call(this, room, fn);
// if we join A and are alreadymember of B, we can join C
if(room === "A" && ~this.rooms.indexOf("B")) {
this.join("C");
} else if(room === "B" && ~this.rooms.indexOf("A")) {
this.join("C");
}
};
})();
Socket.prototype.leave = (function() {
// the original leave method
var oldLeave = Socket.prototype.leave;
return function(room, fn) {
// leave the room as usual
oldLeave.call(this, room, fn);
if(room === "A" || room === "B") {
this.leave("C");
}
};
})();
中的所有用户广播,请广播到C
。
这只是一个示例代码,您可以通过不对房间名称进行硬编码,而是使用数组或对象来循环可能的房间组合来进一步改进这一点。
作为使A
工作的自定义适配器:
B
在你的app文件中:
socket.broadcast.in("A").in("B").emit()
答案 2 :(得分:0)
io.sockets.adapter.room["Room A"].forEach(function(user_a){
io.sockets.adapter.room["Room B"].forEach(function(user_b){
if(user_a.id == user_b.id){
user_a.emit('your event', { your: 'data' });
}
});
});