3

I have a web application running on node using express, angular, mongodb and socket.io where users belong to groups. In those groups I need to set up a chat socket whereby only the people who belong to that group can see the messages specific to that group and only send messages to other users in that group. At the moment I have managed to set up the socket.io chat room based on the guidelines on their site, but the messages sent are visible to all other groups. I have read that I need to set up certain rooms, but I am not sure how to set it up so that the room is specific to the group.

The group is held at a domain: for example... www.mydomain.com/groups/groupId/room

The groupId is a unique Id which is generated by MongoDB. I am using Angularjs on the client side, and have a group controller for the groups. If anyone has any ideas how to achieve this or could point me in the right direction I'd be extremely grateful.

My current server side code:

var io = require('socket.io').listen(server);

io.sockets.on('connection', function(socket) {

    socket.on('connectToServer', function (data) {
        var name = data.name;
        io.sockets.emit('user-join', name + " has connected to the group");
    });

    socket.on('send msg', function (data) {
        io.sockets.emit('get msg', data);
    });

});

and my client side code in the groupController, in which I access a Global service which stores the current user's details is as follows:

var socket = io.connect();

$scope.msgs = [];

$scope.sendMsg = function () {
    socket.emit('send msg', $scope.msg.text);
    $scope.msg.text = "";
}

socket.on('get msg', function (data){
    $scope.msgs.push(data);
});

var currentUser = Global.currentUser();
var name = currentUser.username;

socket.emit('connectToServer', {name: name});

socket.on('user-join', function (data) {
    $scope.msgs.push(data);
});
Shrey Gupta
  • 5,509
  • 8
  • 45
  • 71
StujayH
  • 69
  • 1
  • 9
  • You should make each room an event emitter. http://code.tutsplus.com/tutorials/using-nodes-event-module--net-35941 To scale beyond a single process you might also consider using redis. https://github.com/mranney/node_redis#publish--subscribe – generalhenry Jul 16 '14 at 20:21

1 Answers1

4

I'd recommend setting up namespaces for each room you have your chat in. I did something similar in my own code. Note: Rooms and namespaces are a little different from each other in socket.io itself (socket.io has both: http://socket.io/docs/rooms-and-namespaces/).

In the Server code:

I have a method under socket.on('connection') that is similar to

socket.on('groupConnect', function(group){
    var groupNsp = io.of('/' + group);
}

This essentially makes sure that a namespace is exists under the name of the desired one. It doesn't mess it up or reset the namespace when it is called again.

Then for receiving the messages:

socket.on('message', function(data){
    var msg = data.msg;
    var nsp = data.nsp;
    io.of(nsp).emit('message', msg);
}

You could also add the nsp to the data you have already and then just send the data again to the clients.

Then, in the client code:

var socketOut = io.connect('http://yourdomain:1337/');
var someGroupOrMethodToGetGroup;
socketOut.emit('groupConnect', someGroupOrMethodToGetGroup);
var nsp;
setTimeout(function(){
    socket = io.connect('http://yourdomain:1377/' + someGroupOrMethodToGetGroup);
    socket.on('message', function(msg){
        displayMessage(msg);
    }
    nsp = '/' + someGroupOrMethodToGetGroup;
}, 1500);

Then in my displayMessage code I have:

socketOut.emit('message', { msg: desiredMessage, nsp: nsp });
Blubberguy22
  • 1,344
  • 1
  • 17
  • 29
  • This should work for you, just change the variables around to suit your preexisting code. Good luck with your chat! – Blubberguy22 Jul 17 '14 at 13:53
  • Finally got some time to try and implement this. Thanks so much, this worked perfectly. Really appreciate your help. – StujayH Aug 07 '14 at 11:51
  • 1
    No problem. Good luck with your web application. – Blubberguy22 Aug 07 '14 at 12:31
  • another issue I have ran into, I need to be able to disconnect from the socket via a button. If I call a function when it is clicked such as: function onClick() { socketOut.disconnect(); } on the client side, and then log to the console on the server side 'the user has disconnected' this works, however the socket id on the namespace under the sockets array isn't cleared, if you quit the window then it logs the message and clears the socket array. Not sure why this doesn't work. The code on the server side is: socket.on('disconnect', function() { console.log('user disconnected')} ); – StujayH Aug 10 '14 at 11:47
  • Let me make sure I understand you correctly. You can disconnect from the global socket but not from the namespace socket? – Blubberguy22 Aug 11 '14 at 12:32
  • Yes, if I logged out the namespace to the console it still shows the socket(s) connected – StujayH Aug 11 '14 at 12:50
  • Could you please make a separate question with examples of the problem you are having so it is easier to assist you? – Blubberguy22 Aug 11 '14 at 12:52
  • Not to worry I figured it out. Thanks again for your help – StujayH Aug 14 '14 at 10:22
  • @Blubberguy22 Why you use `setTimeout `? socket.io is for deleting this mehtod: 'request to server over and over!' – Morteza Sepehri Niya Sep 14 '15 at 10:32
  • @MortezaSepehriNiya The timeout is so that the socket.io server isn't set up before the page has at least partially loaded (otherwise it may cause problems). – Blubberguy22 Oct 08 '15 at 13:11
  • @Blubberguy22 can you help me by answering this question of mine http://stackoverflow.com/questions/35860810/socket-io-namespaces-or-rooms-or-both – Bikash Mar 08 '16 at 07:23