52

I want to build a simple chat room system on top of Socket.IO where user can create a new chat room and then people can start chatting.

This sound simple but as the Socket.IO 0.9.4 I'm running now, after reading a few SO posts together with the document on socket.io, i'm getting more and more confused. So, I hope that someone can provide me with instruction that WORK with 0.9.4:

  1. I need a way to subscribe to a room. The room name is chosen by user. When a message is posted in a room, the user should receive it. How should I write the server code, how should I write the client code?

  2. A user can join multiple rooms simultaneously.

  3. I want another system to send a message to all user in a certain room. This 'another system' send the message through a request handled by express. How would I write that request handler?

Phương Nguyễn
  • 8,747
  • 15
  • 62
  • 96

1 Answers1

126

This is all pretty straightforward with the socket.io rooms feature. Take a look at the documentation on LearnBoost wiki.

https://github.com/LearnBoost/socket.io/wiki/Rooms

It allows for being connected to multiple rooms over a single socket. I put together a quick test with the following code.

Server

io.sockets.on('connection', function(client){
    client.on('subscribe', function(room) { 
        console.log('joining room', room);
        client.join(room); 
    })
    
    client.on('unsubscribe', function(room) {  
        console.log('leaving room', room);
        client.leave(room); 
    })

    client.on('send', function(data) {
        console.log('sending message');
        io.sockets.in(data.room).emit('message', data);
    });
});

Client

 var socket = io.connect();
 socket.on('message', function (data) {
  console.log(data);
 });
 
 socket.emit('subscribe', 'roomOne');
 socket.emit('subscribe', 'roomTwo');
 
 $('#send').click(function() {
  var room = $('#room').val(),
   message = $('#message').val();
   
  socket.emit('send', { room: room, message: message });
 });

Sending a message from an Express route is pretty simple as well.

app.post('/send/:room/', function(req, res) {
    var room = req.params.room
        message = req.body;

    io.sockets.in(room).emit('message', { room: room, message: message });

    res.end('message sent');
});
Mr Br
  • 3,831
  • 1
  • 20
  • 24
Timothy Strimple
  • 22,920
  • 6
  • 69
  • 76
  • Is there a way for the client to leave either of the two rooms had join?? – kbariotis Sep 29 '13 at 14:38
  • I'm not sure. You can either store the 2 rooms in an array then do a loop and unsubscribe. Or there may be a disconnect function. (I have never used that) – Phương Nguyễn Oct 14 '13 at 12:09
  • @kbariotis totally. Create a message like `"leave"` and have your client send it with a name of the room he wishes to leave. Then wire up the "disconnect" button to send such message. Server-side, order the socket to leave the given room. – D-side May 13 '15 at 09:23
  • 3
    @Timothy Strimple shouldn't you also listen to socket.on 'disconnect', so the user will automatically unsubscribe from the room if disconnected or does socket.io handles this case for us? – kroe Jun 24 '15 at 19:20
  • 2
    According to socket.io documentation (https://socket.io/docs/rooms-and-namespaces/) : `Upon disconnection, sockets leave all the channels they were part of automatically, and no specially teardown is needed on your part.` – Vinzzz Dec 07 '17 at 17:35
  • Bug: When/If link fails, the socket removed from room. Client will reconnect and no longer get messages sent to the room it was previously registered for. Need to add in the client "socket.on('connect', () => { socket.emit('subscribe', 'roomOne'); socket.emit('subscribe', 'roomTwo');})" Now client will work even if link bounces. – grabbag Sep 07 '19 at 19:28
  • new 2.0 version, replace "io.sockets.in" with "io.in" – grabbag Sep 07 '19 at 19:29
  • There's also a leaveAll function to not be in any rooms – GeekyMonkey Nov 06 '20 at 08:24