Socket.io: Properly getting a socket by ID

Created on 2 Sep 2011  路  18Comments  路  Source: socketio/socket.io

I've asked on IRC what the proper way is to get a socket by id from the normal namespace. Supposedly it would be io.sockets.client(id). Unfortunately, this method does not exist. I figured it'd be a typo, and it should be io.sockets.clients(id). However, the clients method expects a room and then returns an array of all sockets in that room.

Thus, one could get a socket by id like so:

function getSocketById(id) {
    var clients = io.sockets.clients(),
        client  = null;
    clients.forEach(function(_client) {
        if (_client.id === id) return (client = _client);
    });
    return client;
}

This is obviously rather excessive. A much more efficient way would be to access the socket by id through a library (an object where id is the key).

From the source, another way to access a socket by id is io.sockets.socket(id);. Unfortunately, there are 2 problems here:

  • the method is flagged private
  • the method creates a new socket when the given id does not exist

Thus, this method cannot be used as passing an invalid or non-existant id would trigger the creation of a dead socket.

Is there no proper way to get a client from a namespace by id at the moment?

Most helpful comment

io.sockets.sockets is an array of sockets, so you can

var socket = _.findWhere(io.sockets.sockets, {id: 'mySocketId'});

using underscore or

var socket;
for (var i = 0; i < io.sockets.sockets; i += 1) {
  if (io.sockets.sockets[i].id === 'mySocketId') {
    socket = io.sockets.sockets[i];
  }
}

more general. Have in mind that io.sockets is the "/" namespace. For specific namespace: io.of('/ns').sockets.

@romelperez But whole this comments thread is based on a comment of @tommedema stating that using forEach in your case some underscore.js function, is excessive. Not an array but a hash would be more efficient or convenient.

All 18 comments

It was actually io.sockets.socket see https://github.com/LearnBoost/socket.io/blob/master/lib/namespace.js#L202 I could have sworn it was .client().

And it will indeed generate a new client, but there isnt any other way of doing it.. except for looking in the interal client object, which isn't adviced

@3rd-Eden, please read my entire post ;) I did address io.sockets.socket and it has its own issues. Thanks.

@tommedema I noticed that part as was already editing my reply :)

Closing this as proper scalable solutions are in the works!

@tommedema, can you share your proper scalable solution?

@pyrostrex, I'm afraid you misunderstood me. I do not have such solution yet. :)

@tommedema, owh XD. my bad.

If the solution is not there yet, the issue shouldn't be closed.

Can this be re-opened please? There is still no way to easily get a socket by ID without running the risk of creating new sockets.

Going to add in a request to re-open this as well! Would be a very useful addition

I think you can use the io.sockets.sockets property as a hash to get the socket by id like this:

var socket = io.sockets.sockets[socket_id];

Is there a scalable way to do this yet?

For socket.io version 1.0.6, I think you can use this:
var socket = io.sockets.connected[socket.id];

For socket.io version 1.0.6, I think you can use this:
var socket = io.sockets.connected[socket.id];

just as a data point, this doesn't work as of socket.io 1.2.x

io.sockets.sockets is an array of sockets, so you can

var socket = _.findWhere(io.sockets.sockets, {id: 'mySocketId'});

using underscore or

var socket;
for (var i = 0; i < io.sockets.sockets; i += 1) {
  if (io.sockets.sockets[i].id === 'mySocketId') {
    socket = io.sockets.sockets[i];
  }
}

more general. Have in mind that io.sockets is the "/" namespace. For specific namespace: io.of('/ns').sockets.

@romelperez thanks man, that was super helpful, old app stopped working after upgrade because this doesn't work anymore: var socket = io.sockets.sockets[socket_id];, saludos

io.sockets.sockets is an array of sockets, so you can

var socket = _.findWhere(io.sockets.sockets, {id: 'mySocketId'});

using underscore or

var socket;
for (var i = 0; i < io.sockets.sockets; i += 1) {
  if (io.sockets.sockets[i].id === 'mySocketId') {
    socket = io.sockets.sockets[i];
  }
}

more general. Have in mind that io.sockets is the "/" namespace. For specific namespace: io.of('/ns').sockets.

@romelperez But whole this comments thread is based on a comment of @tommedema stating that using forEach in your case some underscore.js function, is excessive. Not an array but a hash would be more efficient or convenient.

For socket.io version 1.0.6, I think you can use this:
var socket = io.sockets.connected[socket.id];

just as a data point, this doesn't work as of socket.io 1.2.x

works fine for me as of socket.io 2.2.2, and it seems to be written in API doc.
See https://github.com/socketio/socket.io/blob/master/docs/API.md#namespaceconnected

Was this page helpful?
0 / 5 - 0 ratings