简体   繁体   English

尽管.to(room),Socket.io仍向所有用户发出

[英]Socket.io emitting to all users despite .to(room)

I have a node.js server that's using Socket.io to emit events to clients. 我有一个使用Socket.io向客户端发出事件的node.js服务器。 When a connection event occurs, the new socket is placed in a room based on the connecting user's id, which is obtained using the session id cookie from socket.headers.handshake.cookie . 发生连接事件时,将根据连接用户的ID将新的套接字放置在房间中,该ID是使用来自socket.headers.handshake.cookie的会话ID cookie获取的。 I know this part is working, because I can set a breakpoint and inspect io.sockets.adapter.rooms and see this room: 我知道这部分正在工作,因为我可以设置一个断点并检查io.sockets.adapter.rooms并看到此房间:

在此处输入图片说明

So, the room apparently has only one socket in it. 因此,房间中显然只有一个插座。 Also while paused at this breakpoint, the following expression: userID.toString() evaluates to: "5cd6201acb0d5f23e465cb84" . 同样,在此断点处暂停时,以下表达式: userID.toString()计算结果为: "5cd6201acb0d5f23e465cb84" So, this expression should be usable to obtain the room with that one socket in it. 因此,该表达式应可用于获得其中有一个插座的房间。 Then, directly after the breakpoint, this code executes: 然后,在断点之后立即执行以下代码:

io.of('/').in(userID.toString()).emit('notification', notifHTML);

So, I would expect the notification event to only be emitted to the one socket in that room identified by that expression. 因此,我希望通知事件仅发送到该表达式所标识的那个房间中的一个套接字。 The notification event is handled by the client thusly: 因此,通知事件由客户端处理:

socket.on('notification', function(notifHTML){
    $("#notificationsContainer").prepend(notifHTML);
    $(".notifications-count").html('<i class="fas fa-dot-circle"></i>');
    document.title = '(⚐) sweet';
});

However, as it turns out, every client connected to the server recieves that notification event and handles it in the above-shown way; 但是,事实证明,连接到服务器的每个客户端都会收到该通知事件并以上述方式处理该事件。 when I have three browsers connected to the server, all three of them execute the above code; 当我有三个连接到服务器的浏览器时,所有这三个浏览器都执行上述代码; I can see the results on the page and in the new document title. 我可以在页面和新文档标题中看到结果。

I actually can fix this by replacing that line that has .to with the following: 实际上,我可以通过将具有.to的行替换为以下内容来解决此问题:

io.of('/').in(userID.toString()).clients(async (error, clients) => {
     for (var client of clients) {
          io.sockets.connected[client].emit('notification', notifHTML);
     }
})

Then, the event is only emitted to the client I want it to be, the one in the room that I showed. 然后,该事件仅发送给我希望成为它的客户端,即我所显示的房间中的那个。 (This room could contain multiple clients if one user connects to the server from multiple browsers, so I can't replace this room code with code to target a single socket.) However, the code shouldn't need to be this verbose; (如果一个用户从多个浏览器连接到服务器,则该会议室可以包含多个客户端,因此我不能用针对单个套接字的代码替换该会议室代码。)但是,代码不必太冗长; I would still like to know why .to is not working the way I expect it to. 我仍然想知道为什么.to无法按我期望的方式工作。 As far as I can tell from reading the docs, it should provide that same functionality of only emitting events to the sockets in a specified room. 据阅读文档所知,它应该提供仅向指定房间中的套接字发出事件的相同功能。

In order to emit events to all the sockets in a particular room, try doing... 为了向特定房间中的所有sockets emit事件,请尝试执行...

io.sockets.in('my-room').emit('my-event', someData);

...this will broadcast the event to all sockets in that room in the default namespace. ...这会将event broadcast到该房间中默认名称空间中的所有sockets You can use of('my-namespace') with io to specify the namespace as well. 您也可以在io使用of('my-namespace')来指定名称空间。 You are missing the sockets part after io in your code. 您在代码中的io之后缺少sockets部分。

Alternatively, doing... 或者,做...

socket.broadcast.to('my-room').emit('my-event', someData);

...will broadcast the event to all the sockets in that room except the one broadcasting. ...会将event broadcast到该房间的所有sockets中,一个广播除外。

Hope this helps :) 希望这可以帮助 :)

使用.to代替.in

io.of('/').to(userID.toString()).emit('notification', notifHTML);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM