Sending messages to certain clients with Socket.io

07 Mar 2013 in Tech

I recently started playing with Socket.io and it's really easy to get up and running. Just copy and paste their example and run the server. Open the page and open the console to see your messages being passed back and forth. I wanted to make a small chat app to play with sending messages to specific users, and it was quite difficult to find out how to do it so I decided to create a small demo app on GitHub.

I started with their example to prove that everything should work. It all worked fine, so I moved on to keeping track of individual clients. It took me ages to realise that events are bound per socket. Once I realised that, I started digging into the socket object and realised that socket.id is the important bit. Push it into an array and you have an array of socket objects that you can write to.

javascript
var clients = [];
io.sockets.on("connection", function (socket) {
clients.push(socket.id);
});

You write to each socket using io.sockets.connected(socket.id).emit("topic", data), so I decided to send a different message to the first two users connected after five seconds:

javascript
setTimeout(function () {
io.sockets.connected[clients[0]].emit("greeting", "Howdy, User 1!");
io.sockets.connected[clients[1]].emit("greeting", "Hey there, User 2");
// If you're using Socket.io < 1.0, you need to use io.sockets.socket instead
// io.sockets.socket(clients[0]).emit("greeting", "Howdy, User 1!");
}, 5000);

This worked fine (you can see the full commit here).

Finally, we needed to route messages to specific clients. I decided to use a username as the unique identifier for a socket, so store the data in an object like so:

javascript
var clients = {
mheap: {
socket: "1hu189dnfd",
},
};

This means that I can now use io.sockets.connected[clients.mheap.socket].emit() to send messages just to myself. As the connection is established instantly when the page loads, there's no way to add metadata to a socket connection on connect (without using socket.auth and a session, which I'll cover some other time). As a result, I ended up listening for a "add-user" message and creating the client when I received it:

javascript
socket.on("add-user", function (data) {
clients[data.username] = {
socket: socket.id,
};
});

You can see the entire thing in the github repo. The frontend depends on a CDN version of jQuery and is horribly written, but it works for demonstrating client management with socket.io.

If you want to give it a go, you can run the following commands:

bash
$ git clone [email protected]:mheap/socketio-chat-example.git && cd socketio-chat-example && npm install && node app.js

Then open http://localhost:3000 in two browser windows, join the chat with a different name in each window and chat away