Node Js, websockets save connections in channels - node.js

Hi I am using websockets with node js server, the npm module is ws. I have an array where I save all my connections but now I have to separate them so I did multidimensional array something like this:
users[channel1][user_id1] = ws_user_id1_connection
The question is when I have 1 user in multiple channels:
users[channel1][user_id1] = ws_user_id1_connection
users[channel2][user_id1] = ws_user_id1_connection
users[channel3][user_id1] = ws_user_id1_connection
From preformance point of view, is this ok?. or I can accomplish this in some other way? And if I leave it like this, Is that users[channel1],users[channel2],users[channel3], they would be only reference to the ws_user_id1_connection. I mean It's not going to add the all data about ws_user_id1_connection when I create new users[channelNew], but only reference to it. The Idea is that I would like to have something as rooms/channels and in each channel to have some connected users so they can talk each other. Is that the right way? Thank you in advance.

Assuming that channel1 is a chat room, user_id1 is the userid in the room, then yes, that's a good way to implement it, you should not create a different ws per channel. You will just need to add some information to the sent data so the client knows what is the room related to the message, something like:
{
'room': 'channel1',
'from': 'otherUser_id',
'msg': 'some text message'
}
I would recommend not to use channel to refer a room because it can be confused with a ws channel. I´d also change the name of the variable ´users´ as it is not referencing users, I´d leave it like: rooms[room_id1][user_id1] = ws_user_id1_connection
Also, you may want to check Socket.io, it is a good Nodejs library designed for that kind of applications.

Related

Android - Socket.io clients in room

Hi all :)
I need to get all clients in a room.
I have found the following code and it's works:
var clients = io.sockets.adapter.rooms['queue'].sockets;
// Output is client ID and true/false value
The issue is that I need the socket ID from each client.
clients.id or clients.socket.id ..
Does not work. Output is undifined.
Has anyone a solution for my issue ?
Second question:
Alternativ was my idea that I put all user ID's if the client is joining in a javascript array or list etc. But if I have above 500 or 1000 clients in a list .. I think that is a little bit unfavorable ?
Thanks
David

How do I manage groups/rooms with node WebSockets?

TL;DR below.
I am currently developing a React/Redux SPA that is driven by real-time data. I've decided to use ws, instead of socket.io since socket.io feels a bit high level for what I'm doing, I'd rather manage sockets myself.
In saying that, I'm struggling to find a way to manage the separation of updates/messages per view/route. Since I'm using client-side routing it's per express route won't really work...
Messages between the server and client via WebSockets are JSON with actions like GET_ITEMS then a response of GET_ITEMS_SUCCESS with an array of 'items' and for errors: ..._ERROR etc. This is all fine, since it's just 1 to 1 transaction. Though the problem arises when broadcasting (1 to all) to all relevant clients when the server receives an update.
So, I assume it best practice to limit these broadcasts to the clients that are viewing/want the data. So when viewing, for example, the Item page, there is no point in broadcasting updates to the User data since that is only used on the User page.
I haven't been able to find any common practices when dealing with this sort of situation, just a few small outdated/barely used wrappers for ws that just add a few basic functions to leave/join but don't offer much flexibility with implementation.
What I think MIGHT work is to have an object/array for each 'group'/'room', which stores the clients that are currently listening to updates from a given section. So a user would send an action to INIT_LISTEN (& ``) with a param of category, e.g. ITEM for updates and other actions related to items.
TL;DR
What my question really boils down to is: How do I store a reference to a single socket? (ws client object? ws client ID?) Then, can I store this in an object/array to iterate through like below.
const ClientRooms = {
Items: {
{
...ws
}
/* ...rest of the client */
}
}
or
const ClientRooms = {
Items: [ "xyz" ] /* Array of ws ids */
}
I have a "ping--pong" heartbeat function to keep clients active and prevent silent connection failures/disconnections. I can't find if ws.terminate() still fires the ws close event so I can iterate 'group'/'room' the object/array to find and remove instances of that client.

socket.io - io.sockets.adapter object?

I'm experimenting with socket.io and trying to build a multi-room chat app. The guide I'm following is out of date using pre 1.0.0 socket.io.
I'm trying to find a list of connected clients in a given room. Googling around shows that I have to use the adapter. However, I cannot find the documentation for it anywhere. I searched for it in the git-hub doc but search didn't return any information on adapter. https://github.com/socketio/socket.io-client/blob/master/docs/API.md
Can someone point me in the right direction and where I can read more about adapter and associated methods on it? Also if you can provide the most up to date documentation for socket.io I'd greatly appreciate it. Thank you.
You can get a map of all rooms in the top level namespace like this:
io.nsps['/'].adapter.rooms
You can list the sockets in one of those rooms like this:
function getSocketsInRoom(room, namespace = '/') {
let room = io.nsps[namespace].adapter.rooms[room];
return room.sockets;
}
As best I can tell, this kind of stuff is simply not documented. I've only discovered things like this by examining how things are stored in the debugger. That may or may not mean it's subject to change in the future - I really have no idea.
sockets:
{ '2v8OmIS4qTGX61-YAAAC': true, '3YnScxOgpmAGhZWsAAAG': true },
length: 2 }
it gives u this output. So it basically gives you the clientId and whether it is connected or not and total number of clients connected to a specific room. When the code below is executed (in server side written in node.js) gives u the above output.There is currently two clients connected to the same room named "hello".
var clientsInRoom = io.sockets.adapter.rooms[room];
but when u write this code below and console log it
var clientsInRoom = io.sockets.adapter.rooms
when single client is connected it will console log this
{ '9mVAHSDwcwnqsF4aAAAA':
Room { sockets: { '9mVAHSDwcwnqsF4aAAAA': true }, length: 1 } }
this crazy '9mVAHSDwcwnqsF4aAAAA' literals is client id which is unique for each client

How can I get socket room name in socket 1.4?

I'm looking for a method or a command line to get the socket room name if possible. Any ideas or tips are highly appreciated! For example if the name of the room is 'roomName', I'm looking to get this value, ty!
A socket.io socket can be in multiple rooms. In fact, it is automatically placed into a room with the same name as the socket.id value when the socket first connects.
If what you're trying to do is get a list of all the rooms a socket is in on the server-side of the connection, you can use socket.rooms. That is an object that lists all the rooms the socket is in. If you want just an array of room names the socket is in, you can use this:
let rooms = Object.keys(socket.rooms);
If you want to eliminate the auto-generated room that matches the socket.id, you can do this:
let rooms = Object.keys(socket.rooms).filter(function(item) {
return item !== socket.id;
});
If you're trying to get this information from the client-end of things, it is not available from the client-side socket. You would have to ask the server which rooms this client is in or you'd have to have a system where the client was kept notified of what rooms it was being put in and it kept track of that data. The socket.io client does not know what rooms it is in.
One other thing to be careful of in socket.io. I've seen some asynchronous behavior in joining rooms which means that if you socket.join("someRoom") and then immediately query socket.rooms, the new room might not be there yet. If you query socket.rooms on the next tick, it will be there. I'm not sure if this always happens or just happens in some circumstances.

How to share an object across all sockets using socket.io?

I am struggling to create an object for storing the number of clients in a room. It would look something like this: { Room0: 1, Room1: 4, Room2: 3}, and whenever a socket connection/disconnection occurs (joins or leaves a room), this object will be updated and all existing sockets can have access to it at all times.
Is there a simple way to do this?
You would set a variable in the global scope (outside of the onMessage or onEvent listeners). Then, in your join rooms code, you would have a part where you would add to the count of the room. It's a crude way to do it.
var rooms = {lobby: 0, kitchen: 0}
Inside your room joining section, lets say they joined the lobby, then you would do this inside that block:
rooms.lobby++
Then, any socket that wants to know the number of people in the lobby need only call:
rooms.lobby

Resources