我正在使用带有socket.io的Node.js进行多人纸牌游戏,还有玩家可以加入的游戏室.
为了加入一个房间,我只需使用:
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); }); });
我的问题是,检查套接字是否连接到某个房间的最快方法是什么?我知道我可以在一个数组中获取该房间中的所有套接字,然后检查目标套接字是否在数组中,但我猜测应该有更基本的语法.我正在寻找(伪代码)将是
if(socket with ID "z8b7dbf98i" is in room "game10") //do something
小智.. 13
对于文档,socket.io似乎没有任何简单的方法来做到这一点.您确实需要检查客户端是否在房间阵列中,或者相反:如果房间在客户端阵列中.
这可以通过oneliner使用indexOf
:
if(socket.rooms.indexOf(room) >= 0)
或者相反的搜索:
if(io.sockets.manager.rooms['/' + room].indexOf(socket.id) >= 0)
Amol M Kulka.. 7
你可以这样检查一下
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'];
如果您使用的是多节点服务器,即具有负载平衡的单独节点进程.
这里要注意的是,套接字仅在它们首次连接的进程上注册.因此,您需要使用socket.io-redis将所有节点连接在一起以同步事件,并且每次客户端连接/断开连接时,您可以执行的维护多节点上的套接字ID列表的事件是广播事件,以便每个节点更新并维护所有客户端/套接字ID的实时列表.
背景/详细信息:
redis适配器扩展了基本适配器,但它只覆盖/添加以下属性:
clients broadcast add del delAll
使用以下代码:
io.sockets.adapter.rooms["roomId"]; //Any of the above examples specific to versions mentioned above
你在socket.io-redis适配器上查询房间属性.这没有被redis适配器覆盖,所以你实际上是在查询基本适配器,它只知道当前进程中的房间/客户端.
为什么redis适配器没有覆盖房间属性?可能是因为它必须查询redis数据库实例以构造一个对象,该对象包含该属性的每次访问的所有房间和连接.不是个好主意?
因此,在撰写本文时,您必须使用以下方法将该功能添加到适配器本身:
/** * 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方法.
返回跨所有节点连接到房间的客户端ID列表.请参阅命名空间#客户端(fn:Function)
io.of('/').adapter.clients((err, clients) => { console.log(clients); // an array containing all connected socket ids }); io.of('/').adapter.clients(['room1', 'room2'], (err, clients) => { console.log(clients); // an array containing socket ids in 'room1' and/or 'room2' }); // you can also use io.in('room3').clients((err, clients) => { console.log(clients); // an array containing socket ids in 'room3' });
快乐的编码!
对于文档,socket.io似乎没有任何简单的方法来做到这一点.您确实需要检查客户端是否在房间阵列中,或者相反:如果房间在客户端阵列中.
这可以通过oneliner使用indexOf
:
if(socket.rooms.indexOf(room) >= 0)
或者相反的搜索:
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'];
如果您使用的是多节点服务器,即具有负载平衡的单独节点进程.
这里要注意的是,套接字仅在它们首次连接的进程上注册.因此,您需要使用socket.io-redis将所有节点连接在一起以同步事件,并且每次客户端连接/断开连接时,您可以执行的维护多节点上的套接字ID列表的事件是广播事件,以便每个节点更新并维护所有客户端/套接字ID的实时列表.
背景/详细信息:
redis适配器扩展了基本适配器,但它只覆盖/添加以下属性:
clients broadcast add del delAll
使用以下代码:
io.sockets.adapter.rooms["roomId"]; //Any of the above examples specific to versions mentioned above
你在socket.io-redis适配器上查询房间属性.这没有被redis适配器覆盖,所以你实际上是在查询基本适配器,它只知道当前进程中的房间/客户端.
为什么redis适配器没有覆盖房间属性?可能是因为它必须查询redis数据库实例以构造一个对象,该对象包含该属性的每次访问的所有房间和连接.不是个好主意?
因此,在撰写本文时,您必须使用以下方法将该功能添加到适配器本身:
/** * 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方法.
返回跨所有节点连接到房间的客户端ID列表.请参阅命名空间#客户端(fn:Function)
io.of('/').adapter.clients((err, clients) => { console.log(clients); // an array containing all connected socket ids }); io.of('/').adapter.clients(['room1', 'room2'], (err, clients) => { console.log(clients); // an array containing socket ids in 'room1' and/or 'room2' }); // you can also use io.in('room3').clients((err, clients) => { console.log(clients); // an array containing socket ids in 'room3' });
快乐的编码!