简体   繁体   中英

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. 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 . I know this part is working, because I can set a breakpoint and inspect io.sockets.adapter.rooms and see this room:

在此处输入图片说明

So, the room apparently has only one socket in it. Also while paused at this breakpoint, the following expression: userID.toString() evaluates to: "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:

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. 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...

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

...this will broadcast the event to all sockets in that room in the default namespace. You can use of('my-namespace') with io to specify the namespace as well. You are missing the sockets part after io in your code.

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.

Hope this helps :)

使用.to代替.in

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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