我使用带有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
答案 0 :(得分:10)
对于文档,socket.io似乎没有任何简单的方法来做到这一点。你真的需要检查客户端是否在房间阵列中,或者相反:如果房间在客户端阵列中。
使用indexOf
:
if(socket.rooms.indexOf(room) >= 0)
或相反的搜索:
if(io.sockets.manager.rooms['/' + room].indexOf(socket.id) >= 0)
答案 1 :(得分:6)
您可以像这样检查
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'];
<小时/> 的更新强>
如果您使用multi-node server,即使用负载平衡的单独节点进程。
这里要注意的是,套接字仅在它们首次连接的进程上注册。因此,您需要使用socket.io-redis将所有节点连接在一起以同步事件,并且每次客户端连接/断开连接时,您可以执行的维护多节点上的套接字ID列表的事件是广播事件节点更新&amp;维护所有客户端/套接字ID的实时列表。
背景/详细信息:
redis适配器扩展base adapter,但只有overrides/adds the following properties:
客户
广播
加
德尔
全删除
使用以下代码:
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数据库实例。
这应该是所有其他适配器实现的基本适配器接口的一部分。这是每天每个人在扩展服务器时都会遇到的常见问题;)
P.S。只是提示另一种方法是使用 socket.io-redis 3.1.0 中的customRequest / customHook方法。
<小时/> 使用ver 5.2.0进行更新:(相关的多节点服务器)
返回跨所有节点连接到房间的客户端ID列表。见Namespace#clients(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'
});
快乐的编码!
答案 2 :(得分:2)
对于当前socket.io
(我认为是1.0+)io
对象的结构已更改,因此您现在可以找到在给定套接字的房间中给定socketid
的用户roomid
:
if(io.sockets.adapter.rooms[roomid][socketid])
答案 3 :(得分:1)
对于socket.io的版本,这似乎已经发生了很大的变化,但是在撰写本文时(版本1.7.2),这看起来像是存储在socket.rooms
中。它是一个看起来像这样的对象:
{
room_name: 'room_name',
second_room_name: 'second_room_name',
...
}
在您的套接字加入任何会议室之前,如您所记录的那样,您已经看到该套接字已经在一个拥有该ID的房间中,因此socket.rooms
将类似于:
{ PxtiIs22S7GhWPTSAAAA: 'PxtiIs22S7GhWPTSAAAA'}
这意味着您可以检查套接字是否在这样的房间中:
io.on('connection', function(socket){
if(socket.rooms[myRoomName]){
// in the room
}else{
// not in the room
}
});
答案 4 :(得分:1)
使用"socket.io": "^2.3.0"
对我有用
if (!(io.sockets.adapter.rooms[room] && io.sockets.adapter.rooms[room].sockets[socket.id]))
// Join room or do any stuff
socket.join('product_' + product_id);
答案 5 :(得分:1)
2021 年的回复:
这让我很头疼,但目前在 Socket IO 的 4.0.2 版本中,socket.rooms
是一个 Javascript Set
,因此您可以检查给定的使用 .has()
:
if (socket.rooms.has('abc')) {
// Do something if socket is in room 'abc'
} else {
// Do something if socket is NOT in room 'abc'
}
如果您需要检查用户是否不在房间里,您可以简单地使用!
:
if (!socket.rooms.has('abc')) {
// Do something if socket is NOT in room 'abc'
}
答案 6 :(得分:0)
如果你仍然需要它,你可以做下一步:
socket.room = "someRoom";
然后简单地检查一下:
if (socket.room !== undefined){
socket.leave(socket.room);
}
答案 7 :(得分:0)
现在socket.rooms看起来像这样:
{
"room1":"room1",
"room2":"room2",
...
"room100":"room100"
}
检查插座是否连接到特定房间的方式:
if(socket.rooms[roomID]) return true;