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/A
或 localhost:3000/B
)来选择属于哪个组。
在 Socket.io 中,我现在想向 A 组中的所有客户端或 B 组中的所有客户端或所有客户端发送消息,而不查看它们的组。
这基本上就像与房间聊天,您可以为特定房间内的所有客户或任何客户发送消息,无论他在哪个房间。
使用 Socket.io 设计这样一个系统的最佳方法是什么?
到目前为止,我一直在尝试使用命名空间,它基本上适用于创建组 A 和 B,但是我失去了向所有客户端发送消息的能力,无论他们在什么房间。至少我不知道如何做到这一点。
我应该如何建模?我应该寻找哪些正确的术语?
更新:根据@sdedelbrock 的回答,我可以使用命名空间或房间:
如果使用命名空间,我无法长时间发送给每个人,无论他们的命名空间如何。这是因为io.sockets
是io.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.sockets
是io.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:命名空间、通道和合作的主要内容,如果未能解决你的问题,请参考以下文章