Socket.io:命名空间、通道和合作

Posted

技术标签:

【中文标题】Socket.io:命名空间、通道和合作【英文标题】:Socket.io: Namespaces, channels & co 【发布时间】:2012-11-10 08:34:00 【问题描述】:

我有一个 Node.js Web 服务器,它在顶部运行一个套接字服务器,它是使用 Socket.io 创建的。基本上,这行得通。

我现在想要实现的是将连接的客户端聚集成组。因此,可能有一些客户端组成 A 组,而其他一些客户端则组成 B 组。它们应通过寻址特定 URL(localhost:3000/Alocalhost:3000/B)来选择属于哪个组。

在 Socket.io 中,我现在想向 A 组中的所有客户端或 B 组中的所有客户端或所有客户端发送消息,而不查看它们的组。

这基本上就像与房间聊天,您可以为特定房间内的所有客户或任何客户发送消息,无论他在哪个房间。

使用 Socket.io 设计这样一个系统的最佳方法是什么?

到目前为止,我一直在尝试使用命名空间,它基本上适用于创建组 A 和 B,但是我失去了向所有客户端发送消息的能力,无论他们在什么房间。至少我不知道如何做到这一点。

我应该如何建模?我应该寻找哪些正确的术语?

更新:根据@sdedelbrock 的回答,我可以使用命名空间或房间:

如果使用命名空间,我无法长时间发送给每个人,无论他们的命名空间如何。这是因为io.socketsio.of('') 的快捷方式,当然它不再匹配命名空间。 这意味着我应该使用房间,但我想知道房间和命名空间之间的语义区别是什么。

简而言之:为什么同一个 (?) 想法有两个概念?

【问题讨论】:

【参考方案1】:

您可能正在使用房间,因此您将执行以下操作以向房间中的每个人发射

io.sockets.in('a').emit('inA', 'foo')

然后发射给你可以使用的每个人

io.sockets.emit('everyone','bar');

您也可以使用命名空间:

io.of('/b').emit('inB', 'buzz');

要向除触发您的用户之外的所有人发出信号:

io.sockets.broadcast.emit("hello");

[编辑] 这是一个更详细的答案:

name-spacing 背后的想法是,它与其他命名空间(甚至是全局命名空间)分开处理。把它想象成一个全新的 socket.io 实例,你可以运行新的握手、新的事件、授权等,而不同的命名空间不会相互干扰。

这对于说/chat/tracking 很有用,其中连接事件的逻辑非常不同

Socket.io 为您完成所有工作,就好像它是两个独立的实例一样,但仍将信息限制在一个连接中,这非常聪明。

可能有一种解决方法,您可以在其中广播到所有命名空间(下面的示例)。但简而言之,您不应该这样做,您应该使用房间。

for (var nameSpace in io.sockets.manager.namespaces)
  io.of(nameSpace).emit("messageToAll", message);

【讨论】:

我试过这个。当使用第二种方法(命名空间)时,无论他们的命名空间如何,我都无法长时间发送给每个人。这是因为io.socketsio.of('') 的快捷方式,当然它不再匹配命名空间。所以这意味着我应该使用房间。无论如何,我想知道房间和命名空间之间的语义区别是什么?为什么同一个 (?) 想法有两个概念? 我相信这样可以将它们分开管理,尽管Socket.io Namespaces 我确实找到了一篇很好的文章 这篇文章绝对是一本好书,可惜它没有回答我的问题。我仍然不明白什么时候应该使用命名空间,什么时候使用房间,以及它们之间的语义差异是什么。此外:我如何向所有客户端发送消息,而不管它们的命名空间如何? 你好@Golo Roden,有点晚了,但我现在已经遇到了。我认为简而言之,房间应该用于处理不同地方的套接字上的相同行为(聊天室最简单的例子)但命名空间应该用于跟踪不同的事物,例如实时新闻提要与聊天室。希望为任何人增添更多的光芒。感谢您的提问和回答! 这个io.sockets.broadcast.emit 不正确,broadcast 需要知道要排除/忽略哪个套接字ID,因此您有两个选择:1)来自全局 io -> io.sockets.in(namespace).socket(socketID).broadcast.emit("hello") 或 2)来自套接字->socket.broadcast.emit("hello")【参考方案2】:

这是您可以使用的模板应用程序(适用于 9.16;未在 1.x 上测试,但应该可以使用):

var namespaces = [
    io.of('/ns1'),
    io.of('/ns2'),
    io.of('/ns3')
];

for (i in namespaces) 
    namespaces[i].on('connection',handleConnection(namespaces[i]));  


function handleConnection(ns) 
   return function (socket) //connection
   console.log("connected ");
   socket.on('setUsername',setUsernameCallback(socket,ns));                       
   socket.on('disconnect', disconnectCallback(socket,ns));                        
   socket.on('messageChat',messageChatCallback(socket,ns));
   socket.on('createJoinRoom',createJoinRoomCallback(socket,ns));  

  ;


function disconnectCallback(socket,ns) 
    return function(msg)
    console.log("Disconnected ");
    socket.broadcast.send("It works!");
  ;

你可以自己写其他句柄:)

【讨论】:

以上是关于Socket.io:命名空间、通道和合作的主要内容,如果未能解决你的问题,请参考以下文章

动态命名空间 Socket.IO

Socket.io 命名空间限制以及如何扩展它

使用特定路径和命名空间连接到 Socket.IO 服务器

Socket.io 命名空间和服务器不共享中间件?

socket.io切换命名空间

socket.io - 如何在命名空间上广播消息?