0

I was following a node.js/express/socket.io tutorial which uses an old version of socket.io (v0.9.17) and in such as cases i always try to rewrite the code using latest versions of each package and adapting it to this change.

The tutorial's app consists on a chat application : after being authenticated, users will be redirected to a "chat rooms list" where they can create their own room or join an already created one. Once a room is joined by a user, he will be redirected to the room page from which a socket connection is established to the /messages name space :

var messages = io.connect(host + "/messages");

and when it happens a joinroom event is emited to make the user join the particular room he has selected carrying with it the username, picture and the room number(which is actually its id):

on the client side :

messages.on('connect', function(){
    console.log('Socket connection established on the client on room!!');
    messages.emit('joinroom', {room:roomNum, user:userName, userPic:userPic})});
});

and in the server side the user data sent is attached to the socket itself:

     var messages = io.of('/messages').on('connection', function(socket) {

                     socket.on('joinroom', function(data) {
                     socket.username = data.user;
                     socket.userPic = data.userPic;

                     // logging the socket at this level
                     console.log('### 000 ------> socket : ' + simpleStringify(socket) + '\n\n');      


                         console.log('user : ' + data.user + ' gonna join room : ' + data.room);
                         socket.join(data.room);
                         updateUserList(data.room, true);                         
                 });
}

the log showing the socket shows all the user's data among other fields

### 000 ------> socket : {"id":"/messages#wGAKwTtHtYdO7NL6AAAC","connected":true
,"disconnected":false,"_eventsCount":3,"username":"Crystaleez Comptedetestt","us
erPic":"https://scontent.xx.fbcdn.net/v/t1.0-1/c23.14.178.178/s50x50/224774_1129
37845457338_611202_n.jpg?oh=0c8b07b2b1bdfbd2e7b4c874d2045507&oe=58B8DBD9"}

The updateUserList function written just after the user joins the room consists mainly to retrieve all connected clients (or sockets) to the chat room ( in the v0.9.17 this was done like this :

var clients = io.sockets.clients('room'); // all users from room `room` 

and a userList is made to be emited back to the client side in order to refresh the chat's users list:

var userlist = [];
for(var i in clients) {
    userlist.push({user:clients[i].username, userPic:[clients[i].userPic});
}
socket.to(room).emit('updateUserList', JSON.stringify(userlist));

but in recent versions it became as the following :

io.of('/chat').clients(function(error, clients){
  if (error) throw error;
  console.log(clients); // => [PZDoMHjiu8PYfRiKAAAF, Anw2LatarvGVVXEIAAAD] 
});

and that's what i used on the updateUserList function code, but then when i tried to get the room sockets themselves that wasn't possible and i tried it by several ways (i gave as labels to the log written before each case (AAA), (BBB) and (CCC) (P.S : i'm using the simpleStringify function to avoid the Converting circular structure to JSON problem when using JSON.stringify() for logging js Objects):

function updateUserList(room, updateAll) {

     io.of('/messages').clients(function(error, clients) {
                     if (error) throw error;                         

                     console.log('\n\n\n\n(AAA)******* USING Object.keys(io.sockets.sockets) ********');
                     Object.keys(io.sockets.sockets).forEach(function(id) {
                        console.log("ID:",id)  // socketId
                        console.log('### 444 ------> socket[ID] : ' + simpleStringify(io.sockets.sockets[id]));
                    })

                     console.log('\n\n\n\n(BBB)******* USING socket_ids = Object.keys(io.of(\'/namespace\').sockets ********');
                     var socket_ids = Object.keys(io.of('/messages').sockets);
                     console.log('### 555 ------> socket_ids : ' + socket_ids);
                     socket_ids.forEach(function(socket_id) {
                         console.log("socket_id:" + socket_id)  // socketId
                         console.log('### 444 ------> socket[ID] : ' + simpleStringify(io.of('/namespace').sockets[socket_id]));

                     });


                     console.log('\n\n\n\n(CCC)******* USING Object.keys(io.sockets.connected)  ********');
                     var allConnectedClients = Object.keys(io.sockets.connected);
                     console.log('### 666 ------> allConnectedClients : ' + allConnectedClients);

                     allConnectedClients.forEach(function(socket_id) {
                         var socket = io.sockets.connected[socket_id];

                         console.log('\n\n socket_id : ' + socket_id + ' ------> socket : ' + simpleStringify(socket));
                         console.log('\n\n socket_id : ' + socket_id + ' ------> connected : ' + socket.connected);
                         /*if (socket.connected) {
                             // Do something...
                         }*/
                     });

                    //here is the code waiting for the sockets to be retrieved to work.. 
                     /*var userlist = [];
                    for(var i in clients) {
                        userlist.push({user:theMissingSocket.username, userPic:theMissingSocket.userPic});
                    }
                    socket.to(room).emit('updateUserList', JSON.stringify(userlist));

                    if(updateAll) socket.broadcast.to(room).emit('updateUserList', JSON.stringify(userlist));*/
                 });

             }

For both the (AAA) and the (CCC) cases , sockets could be retrieved but wihout the user data added to it above, here is their loggings (only the "id","connected" and "disc onnected" remains ):

(AAA)******* USING Object.keys(io.sockets.sockets) ********
ID: IaLjQS2IxQI3FcYSAAAB
### 444 ------> socket[ID] : {"id":"IaLjQS2IxQI3FcYSAAAB","connected":true,"disc
onnected":false}
ID: wGAKwTtHtYdO7NL6AAAC
### 444 ------> socket[ID] : {"id":"wGAKwTtHtYdO7NL6AAAC","connected":true,"disc
onnected":false}


(CCC)******* USING Object.keys(io.sockets.connected)  ********
### 666 ------> allConnectedClients : IaLjQS2IxQI3FcYSAAAB,wGAKwTtHtYdO7NL6AAAC


 socket_id : IaLjQS2IxQI3FcYSAAAB ------> socket : {"id":"IaLjQS2IxQI3FcYSAAAB",
"connected":true,"disconnected":false}


 socket_id : IaLjQS2IxQI3FcYSAAAB ------> connected : true


 socket_id : wGAKwTtHtYdO7NL6AAAC ------> socket : {"id":"wGAKwTtHtYdO7NL6AAAC",
"connected":true,"disconnected":false}

for the (BBB) case, i couldn't get the sockets at all:

(BBB)******* USING socket_ids = Object.keys(io.of('/namespace').sockets ********

### 555 ------> socket_ids : /messages#wGAKwTtHtYdO7NL6AAAC
socket_id:/messages#wGAKwTtHtYdO7NL6AAAC
### 444 ------> socket[ID] : {}
Community
  • 1
  • 1
Bardelman
  • 2,176
  • 7
  • 43
  • 70

1 Answers1

1

You can try the following function:

function findClients(room, namespace) {
    'use strict';
    var res = [];
    var ns = io.of(namespace || "/");

    if (ns) {
        Object.keys(ns.connected).forEach(function (id) {
            if (room) {
                var roomKeys = Object.keys(ns.connected[id].rooms);
                roomKeys.forEach(function (key) {
                    if (key === room) {
                        res.push(ns.connected[id].client.id);
                    }
                });
            } else {
                res.push(ns.connected[id].client.id);
            }
        });
    }
    return res.sort();
}

and test it in a simple example:

server.js

const io = require('socket.io')(3000);
var counter = 0;

function findClients(room, namespace) {
    'use strict';
    var res = [];
    var ns = io.of(namespace || "/");

    if (ns) {
        Object.keys(ns.connected).forEach(function (id) {
            if (room) {
                var roomKeys = Object.keys(ns.connected[id].rooms);
                roomKeys.forEach(function (key) {
                    if (key === room) {
                        res.push(ns.connected[id].client.id);
                    }
                });
            } else {
                res.push(ns.connected[id].client.id);
            }
        });
    }
    return res.sort();
}

io.of('/messages').on('connection', function (socket) {
    'use strict';
    socket.join('room' + (counter % 2));
    console.log(socket.client.id + ' connected to room' + (counter % 2));
    counter += 1;
    setTimeout(function () {
        console.log('Clients connected to room0: ' + findClients('room0', '/messages'));
        console.log('Clients connected to room1: ' + findClients('room1', '/messages'));
    }, 0);
});
console.log('Plain socket.io server started at port 3000');

client.js

const socket = require('socket.io-client')('http://localhost:3000/messages');
socket.on('connect', function () {
    console.log('connected');
});

Run several instances of client.js and check the server messages. It seems to work as you need.

mk12ok
  • 1,293
  • 14
  • 14
  • Thanks alot !! that function returns clients IDs which i already could get but when i digged deeper in its code i could find the connected sockets themselves with all the data previously stored on them using Object.keys(io.of('/messages').connected).forEach(function(id){ console.log('### ns.connected[' + id + ']: ' + simpleStringify(io.of('/messages').connected[id])); }); – Bardelman Dec 10 '16 at 07:00