socket.io仅向位于房间A和B的用户广播

时间:2015-07-09 12:35:01

标签: javascript node.js sockets socket.io

是否可以对位于A房间和B房间的名称空间的所有用户进行socket.io广播,而不是那些位于A房间或B房间的用户?

如果没有,我将如何自己实施?有没有办法检索名称空间中属于给定房间的所有用户?

我在节点

中使用socket.io 1.0

编辑: 如果没有本机方法,我将如何创建自己的语法,例如: const char oldhtml[]

3 个答案:

答案 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.emithttps://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.jsSocket.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' });
    }
  });
});