Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: Emitting to specific socket IDs - won't emit to itself #3220

Closed
peppies opened this issue Apr 10, 2018 · 6 comments · Fixed by #3232
Closed

BUG: Emitting to specific socket IDs - won't emit to itself #3220

peppies opened this issue Apr 10, 2018 · 6 comments · Fixed by #3232

Comments

@peppies
Copy link

peppies commented Apr 10, 2018

Greetings,

I noticed a bug today, trying to do something simple, took a few hours to realize it was a bug. Let's say a user has multiple tabs open in their browser, and then they turn their "Away" status to "Online":

Client side:

socket.emit('update.online.status', userid);

Server side:

socket.on('update.online.status', function(userid) {
  client.smembers('sockets:'+userid, function(err, reply) { // redis: array of user's socket ids (multiple browser tabs)
    reply.forEach(function(sockid) { // loop through all of the user's sockets
      socket.to(sockid).emit('test', 'test');
    });
  });
});

The server emits a "test" response back to all of the sockets (browser tabs) except the originating socket (tab). In my script, the "Online" status gets updated in all of the user's browser tabs - except the one tab where they actually set their online status (and fires off the socket emission to the server).

The only solution would be to use socket.emit('test', 'test') if the originating socket == sockid. That additional logic on the server side should not be necessary and should work using socket.to(sockid).emit. Therefore this is a bug.

Thanks
Kind regards
Ryan

Edit by @darrachequesne: style

@peppies
Copy link
Author

peppies commented Apr 10, 2018

Unfortunately, I cannot edit the post, but I am using Socket.io version 2.0.3

@blackfish-wu
Copy link

blackfish-wu commented Apr 24, 2018

I have the same question while running this code:
socket.to(socket.id).emit('hey');
Could anybody tell us how to emit a private message to the socket itself ?

@darrachequesne
Copy link
Member

According to the documentation, socket.to(sockid).emit('test', 'test'); emits to all clients in sockid room except the sender itself, I think that's why it fails for the tab associated with the given socket.

Two solutions:

  • use io.to(sockid).emit('test', 'test'); instead
  • make each socket join the userid room, and then use io.to(userid).emit('test', 'test');

@blackfish-wu socket.emit('hey'); should be enough

@peppies
Copy link
Author

peppies commented Apr 25, 2018

According to the [documentation] (https://socket.io/docs/emit-cheatsheet/), it also says:

// sending to individual socketid (private message)
  socket.to(<socketid>).emit('hey', 'I just met you');

This is confusing, it is assumed that this command will send a message to any specific socketid. Maybe update the cheatsheet to use "io.to" instead of "socket.to" in this instance. Had the same confusion with a different part of developing my private messaging script the other day until I again realized I had to remember this issue.

However, darrachequesne's solution of using io.to(sockid).emit('test', 'test'); does work as expected and I will probably just use this. However:

Question for darrachequesne

If there is a very large number of socket connections, is there a performance difference for using "io.to" vs "socket.to" when emitting to individual socket ids?

darrachequesne added a commit that referenced this issue Apr 27, 2018
The previous version was confusing, as `socket.to(socket.id).emit()` does nothing.

Fixes #3220
darrachequesne added a commit that referenced this issue Apr 27, 2018
The previous version was confusing, as `socket.to(socket.id).emit()` does nothing.

Fixes #3220
@darrachequesne
Copy link
Member

@peppies you're absolutely right, thanks for the explanation! I updated the documentation in #3232.

Regarding the performance, both methods actually call the same code:

https://github.com/socketio/socket.io/blob/master/lib/namespace.js#L234-L237

this.adapter.broadcast(packet, {
  rooms: rooms,
  flags: flags
});

https://github.com/socketio/socket.io/blob/master/lib/socket.js#L170-L173

this.adapter.broadcast(packet, {
  except: [this.id],
  rooms: rooms,
  flags: flags
});

@592da
Copy link

592da commented Nov 12, 2019

@darrachequesne ack not working when emitting to specific socket. ex:

io.to(socketId).emit(MESSAGE_TYPE, data, function(
            error,
            resposne
          ) {
            console.log({ error, resposne });
          });

when sending with ack function, message not sent.
when sending without ack, message sent.

how to solve it?
thee use case is to send a message from server to specific client id, with ack function.

Thank you.

dzad pushed a commit to dzad/socket.io that referenced this issue May 29, 2023
The previous version was confusing, as `socket.to(socket.id).emit()` does nothing.

Fixes socketio#3220
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants