socket io房间的名称和特定房间内的用户数

时间:2018-10-22 20:09:09

标签: javascript node.js socket.io

我正在尝试使用socket.io版本建立一些基本的聊天室(基于房间):

"socket.io": "^2.1.1"
"socket.io-client": "^2.1.1"

我有几个基本问​​题,无论我寻找它们的深度如何,都找不到有效的答案。

  1. 当用户进入特定房间时,我正在做(在服务器中) socket.join(roomName)这样,仅当至少有一个插座连接到该房间时,房间才“存在”吗?

  2. 我想创建一个包含房间名称和参加人数的屏幕-(是否可以通过客户端socketIO的对象获取它?),我发现可以获取房间名称(服务器端)使用io.sockets.adapter.rooms,但我得到的字符串确实很奇怪,这绝对不是房间名称。

  3. 我正在尝试在每个房间内创建一个页面,以显示连接到该房间的用户(通过socket.join(roomName)进入房间的连接)

我是socket.io的新手,我希望有人可以帮助我更好地了解如何使用它,以及我在这里缺少的内容。

谢谢!

2 个答案:

答案 0 :(得分:9)

实际上,只有有一个客户端连接到socket.io会议室,该会议室才存在。此外,一旦最后一个客户端在套接字适配器中将其保留为shown here,它就会被销毁以释放内存:

if (this.rooms[room].length === 0) delete this.rooms[room];

要获取真实的房间名称,您必须在服务器端对其进行跟踪。最简单的方法是通过房间名称索引用户计数对象。

const usersByRooms = {}

当新的套接字连接时,您将首先发送该完整对象

socket.emit('getAllRooms' usersByRoom)

并在客户端收到对象时通过其键迭代该对象

socket.on('getAllRooms', (usersByRoom) => {
  Object.keys(usersByRoom).forEach(roomName =>
    console.log(roomName, usersByRoom[roomName]))
})

我假设您的页面需要实时更新连接到您房间的客户端数量。为此,您需要一种方法来广播要更改房间的用户数,并相应地更新usersByRooms缓存,如下所示:

const updateCount = roomName => {
  const userCount = io.sockets.clients(roomName).length
  // we do not update if the count did not change
  if (userCount === usersByRoom[roomName]) { return }
  usersByRoom[roomName] = userCount
  io.emit('updateCount', { roomName, userCount })
}

每次使用以下两种方法的回调,每次套接字加入并成功离开房间时都需要调用此方法:

socket.join(roomName, () => {
  updateCount(roomName)
})

socket.leave(roomName, () => {
  updateCount(roomName)
})

您现在可以进入socket.io#2332中添加的新disconnecting事件,以防客户端断开连接或仅关闭应用程序以将新计数广播到套接字连接到的任何房间。

socket.on('disconnecting', () => {
  const rooms = socket.rooms.slice()
  // ...
})

这种方法可能有点棘手,因为您需要跟踪套接字的房间断开连接,并在套接字完成断开连接后立即进行更新。

一种更简单的方法是在每次套接字断开连接后立即遍历所有房间并调用updateCount,因为该方法仅在房间的用户数量发生变化时广播事件,所以应该很好你有成千上万的房间。

socket.on('disconnected', () => {
  Object.keys(usersByRooms).forEach(updateCount)
})

请注意,如果您使用套接字集群,会有些棘手,但我假设使用的是正常设置。

答案 1 :(得分:4)

  1. 是的,仅当房间中至少有一个成员时才存在;如果当前没有任何成员,则呼叫socket.join(roomName)将创建一个房间。

  2. 好的,所以检查io.sockets.adapter.rooms是在内部检查的方法,因为(从文档中)您仅看到的奇怪字符串是套接字ID:'为方便起见,每个套接字自动加入由其ID标识的房间(请参阅Socket#id)。这使得将消息广播到其他套接字的套接字ID看起来很像:'PZDoMHjiu8PYfRiKAAAF'

    如果只想列出房间列表,则需要跟踪定义的房间名称,而不要依赖socket.io状态。

  3. 获取连接到房间的插座列表的操作如下:

    let socketsOfRoom1 = io.sockets.clients('chatroom1');
    let numberOfClientsInRoom1 = socketsOfRoom1.length;
    
    console.log(numberOfClientsInRoom1);
    socketsOfRoom1.forEach((socket) => {
        console.log(socket)
    });