一线检查sockets是否在给定的房间?

我使用Node.js和socket.io进行多人纸牌游戏,并且有一些玩家可以join的游戏室。

join一个房间,我只是使用:

io.sockets.on('connection', function (socket) { socket.on('joinRoom', function (gid) { //gid is game ID - create room name based on this and join the room var room = 'game'+gid; socket.join(room); }); }); 

我的问题是,检查套接字是否连接到某个房间的最快方法是什么? 我知道我可以在数组中find所有的套接字,然后检查目标套接字是否在数组中,但我猜应该有一个更基本的语法。 我正在寻找(在伪代码)将是

 if(socket with ID "z8b7dbf98i" is in room "game10") //do something 

对于文档,socket.io似乎没有任何简单的方法来做到这一点。 您真的需要检查客户端是否在房间数组中,或者相反:如果房间在客户端数组中。

这可以通过使用indexOf的oneliner来完成:

 if(socket.rooms.indexOf(room) >= 0) 

或者相反的search:

 if(io.sockets.manager.rooms['/' + room].indexOf(socket.id) >= 0) 

你可以简单地这样检查
io.sockets.adapter.rooms['roomId']

这会返回一个带有sId的对象
{"1sEAEIZeuMgdhF35AAAA":true}


特定于版本的更新:

1.4+:

 io.sockets.adapter.rooms['roomId'] 

1.3.x的:

 io.sockets.adapter.rooms['roomId']; 

1.0.x到1.2.x:

 io.adapter.rooms['roomId']; 

更新:
但是,只有在服务器体系结构具有单节点服务器/单节点进程的情况下,才可以检查套接字Id是否在上面提到的单行中。

如果您正在使用多节点服务器 ,即单独的节点进程与负载平衡。

这里需要注意的是,套接字只在他们第一次连接的进程上注册。 因此,您需要使用socket.io-redis将所有节点连接到一起以同步事件,并且您可以在多节点上维护套接字ID的列表时每次客户端连接/断开时都会广播一个事件,以便每个节点更新并维护所有客户端/套接字ID的实时列表。

背景/详细信息:
redis适配器扩展了基本适配器 ,但它只覆盖/添加以下属性 :
客户端播放del delAll

用下面的代码:

 io.sockets.adapter.rooms["roomId"]; //Any of the above examples specific to versions mentioned above 

您正在查询socket.io-redis适配器上的房间属性。 这不会被redis适配器覆盖,所以你实际上正在查询基本适配器,它只知道当前进程中的房间/客户端。

为什么redis适配器不覆盖房间属性? 可能是因为它将不得不查询redis数据库实例来构造一个包含此属性的每个访问权限上的所有房间和连接的对象。 不是一个好主意?

因此,在撰写答案时,您必须使用如下方法将该function添加到适配器本身:

 /** * One-Line code/property to check if the socket id is in given room. * * @param {String} room id * @param {Function} callback (optional) * @api public */ Redis.prototype.isSidExistsInRoom = function(room, fn){ ... } 

你将在哪里点击redis数据库实例。

这应该是所有其他适配器实现的基础适配器接口的一部分。 当他们扩展服务器时,每个人都会遇到一个普遍的问题;)

PS只是提示另一种方法是在socket.io-redis 3.1.0中使用customRequest / customHook方法。 但是如果有人在面对这个问题的时候做了奇迹,请在这里评论你的解决scheme:)
快乐编码!

对于当前的socket.io (1.0+我猜) io对象的结构已经改变,因此你现在可以通过以下方法socketid在给定socketid的房间里是否有给定roomid的用户:

if(io.sockets.adapter.rooms[roomid][socketid])

这似乎已经改变了很多socket.io的版本,但是在写这篇文章时(版本1.7.2),这看起来好像存储在socket.rooms 。 这是一个像这样的对象:

 { room_name: 'room_name', second_room_name: 'second_room_name', ... } 

在您的套接字join任何房间之前,如文档所述,您将看到套接字已经在自己的ID中,因此socket.rooms看起来如下所示:

 { PxtiIs22S7GhWPTSAAAA: 'PxtiIs22S7GhWPTSAAAA'} 

这意味着你可以检查一个套接字是否在一个房间里,像这样:

 io.on('connection', function(socket){ if(socket.rooms[myRoomName]){ // in the room }else{ // not in the room } }); 

如果你仍然需要它,你可以下一步:

  socket.room = "someRoom"; 

然后简单地检查一下:

  if (socket.room !== undefined){ socket.leave(socket.room); }