【问题标题】:Wy should I use namespaces when building a chat wit Socket.io?与 Socket.io 建立聊天时为什么要使用命名空间?
【发布时间】:2019-03-29 09:48:20
【问题描述】:

我正在构建一个平台,多个用户可以在该平台上相互交互,并在另一个用户以某种方式与自己交互时收到通知。例如发送消息、发送请求或更新服务器上的一些协作对象。这里没什么特别的。 因此,我喜欢在带有 express 的节点服务器上使用 Socket.io(前端为 Angular 7),以尽可能保持用户体验的实时性。

我想知道我是否真的需要引入命名空间和房间,因为我当前的实现应该运行良好。你能告诉我,如果我的实现类型有问题吗?

我正在使用某种套接字连接存储作为映射,我所有的活动套接字连接都在其中。这是我的服务器端实现的示例:

// <userId, socket>
var Connections = new Map();

removeConnection = function(socket) {
  console.log("removing User with Id = " + socket.userId);
  Connections.delete(socket.userId);
} 

io.on('connection', (socket) => {

  socket.on('register', (userId) => {
    // do some authentication here..
    socket.userId = userId;
    Connections.set(userId, socket);
    console.log("User registered with id " + userId);
  });

  socket.on('disconnect', () => {
    removeConnection(socket);
  });

  socket.on('new_message', (data) => {
    // persist data in DB and so on..

    socket.emit('new_message', data);
    var receiver = Connections.get(data.receiverId);    
    // if receiver is online send message
    if(receiver) {
      receiver.emit('new_message', data);
    }
  });

});

【问题讨论】:

    标签: socket.io


    【解决方案1】:

    如果您没有使用任何收件人选择(例如,单个收件人或命名空间/房间),那么每封邮件都会发送给每个客户。假设每个客户端在连接后都会发送一条“hello”消息。 “你好”消息的数量会随着您的客户数量呈指数增长。

    取决于您计划扩展可能会导致大量流量的应用程序的规模:n 条消息将导致 n² 个事务... 1000 个用户发送 1 条消息,每个用户已经是 1.000.000 个事务..

    为了提高沟通效率,您可以执行以下任何步骤:

    • 发给单个用户的直接消息应该只发送给该用户,而不是整个平台上的广播网。您可以使用 connection.emit("the message") 命令来做到这一点。 io.emit("the message") 将发送到每个连接的客户端

    • 有关并非所有用户都感兴趣的特定主题的消息可以使用“房间”来实现。任何用户都可以订阅任意数量的房间来接收这些通知。所有其他人都不会收到垃圾邮件。 (https://socket.io/docs/rooms-and-namespaces/)

    另一个问题可能是隐私...如果用户 A 正在向用户 B 发送消息,那么您不希望用户 C、D、E.. 也接收该广播。即使您的客户过滤掉不适合用户的消息,这些信息仍会以纯文本形式发送给所有用户,我认为这是不必要的隐私泄露。

    这里有一份关于收件人选择和不同发送消息方法的备忘单: https://socket.io/docs/emit-cheatsheet/

    您的代码从任何连接的客户端接收消息,并将其仅转发给相应的收件人(如果在地图中找到)。这对于用户之间的直接消息传递来说很好。如果您想广播某个协作项目的更新信息,您应该使用如上所述的房间和命名空间。

    【讨论】:

    • 感谢您的回答。我想知道你说的是否也适合我。在我的情况下,每个客户端都有自己的套接字连接,具有自己的 url,例如:ws://localhost:9500/socket.io-client/?token=eyJhbGciOiJSUzI1。因此,当我在特定套接字连接中发出事件时,没有广播。 (我希望)其他连接不接收消息,只有发送者和收件人。我说的对吗?
    • 使用 socket.io,服务器与每个客户端都有一个单独的“连接”——这是标准过程。 Socket.io 提供了许多不同的方法来选择那些连接的客户端的子集作为recipents。这里对所有这些方法进行了很好的概述:socket.io/docs/emit-cheatsheet 您的代码似乎很好。您的命令“receiver.emit()”仅发送到该连接上的客户端。 "socket.emit()" 将发送给所有客户端。
    猜你喜欢
    • 2020-11-24
    • 1970-01-01
    • 2011-03-20
    • 2011-11-18
    • 2016-04-12
    • 2015-02-10
    • 1970-01-01
    • 2020-08-07
    • 2012-02-08
    相关资源
    最近更新 更多