首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >单行检查套接字是否在指定房间内?

问单行检查套接字是否在指定房间内?
EN

Stack Overflow用户
提问于 2014-04-13 16:30:39
回答 9查看 32.3K关注 0票数 21

我用Node.js和socket.io玩多人纸牌游戏,还有游戏室,玩家可以加入。

在加入一个房间时,我简单地使用:

代码语言:javascript
复制
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);
    });
});

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

代码语言:javascript
复制
if(socket with ID "z8b7dbf98i" is in room "game10")
    //do something
EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2014-04-13 17:37:56

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

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

代码语言:javascript
复制
if(socket.rooms.indexOf(room) >= 0)

或者相反的搜索:

代码语言:javascript
复制
if(io.sockets.manager.rooms['/' + room].indexOf(socket.id) >= 0)
票数 19
EN

Stack Overflow用户

发布于 2017-05-16 10:02:37

你可以这样检查

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

这将返回一个带有sId的对象。

{"1sEAEIZeuMgdhF35AAAA":true}

特定于版本的更新: 3.0+:

代码语言:javascript
复制
io.sockets.adapter.get('roomId')

1.4:

代码语言:javascript
复制
io.sockets.adapter.rooms['roomId']

1.3.x:

代码语言:javascript
复制
io.sockets.adapter.rooms['roomId']; 

1.0.x至1.2.x:

代码语言:javascript
复制
io.adapter.rooms['roomId'];

**最新情况:**

但是,可以检查套接字Id是否在给定的房间中,就像上面提到的那样,只有当服务器体系结构有单个节点服务器/单个节点进程时,才能检查套接字Id是否在给定的房间中。

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

这里要注意的是,套接字只在它们首先连接的进程上注册。因此,您需要使用socket.io-redis将所有节点连接到一起以同步事件,而在多节点之间维护套接字is列表的方法是在客户端每次连接/断开连接时广播一个事件,以便每个节点更新&维护所有客户端/套接字is的实时列表。

Background/Details:

redis适配器扩展了基座适配器,但它只扩展了重写/添加以下属性:

客户端广播添加del delAll

使用以下代码:

代码语言:javascript
复制
io.sockets.adapter.rooms["roomId"]; //Any of the above examples specific to versions mentioned above

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

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

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

代码语言:javascript
复制
/**
   * 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数据库实例。

这应该是所有其他适配器实现的基本适配器接口的一部分。这是每个人总有一天会面临的一个常见问题,当他们扩展服务器时;)

另一种方法就是在socket.io-redis 3.1.0中使用customRequest/customHook方法。

**使用Ver5.2.0更新:(相关多节点服务器)**

现在,redis适配器从5.2.0开始为您提供跨进程/节点的空间。

源:RedisAdapter#clients(房间:数组,fn:Function) >返回连接到所有节点的房间的客户ID列表。参见Namespace#clients(fn:Function)

代码语言:javascript
复制
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'
});

编码愉快!

票数 16
EN

Stack Overflow用户

发布于 2021-06-08 20:21:28

2021回应:

这让我很头疼,但目前在版本4.0.2版的Socket IO中,socket.rooms是Javascript Set,所以您可以使用.has()检查给定的套接字是否在房间里。

代码语言:javascript
复制
if (socket.rooms.has('abc')) {
  // Do something if socket is in room 'abc'
} else {
  // Do something if socket is NOT in room 'abc'
}

如果您需要检查用户是否不在房间,只需使用!即可。

代码语言:javascript
复制
if (!socket.rooms.has('abc')) {
  // Do something if socket is NOT in room 'abc'
}
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23045245

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档