Design pattern for WebSockets through Socket.IO - node.js

I am building a complex chatting application, using WebSockets. I use Node.JS's Socket.IO library to implement the protocol. Should I create a separate namespace for each Chat, Or separate room for each Chat?
What is the main difference between Namespaces and Rooms in Socket.IO?

Typically rooms are used if all the clients are of the same type.
Use namespaces if there are different types of clients. For example, anonymous users and authenticated users. In this case one may need to process incoming connection requests differently.
var guest = io.of('/guest');
guest.on('connection', function(socket) {
console.log('A guest client connected');
});
var user = io.of('/user');
user.on('connection', function(socket) {
var authenticated = authenticate(); //authenticate the user
if (!authenticated) {
// log attempt and disconnect the client
}
});

Related

Socket.io client specific variable

How do I store session specific info in Socket.io?
var client={}; //is this static across all sockets (or connected clients) that are connected?
io.on('connection', function(socket){
client.connectiontime=Date.now();
});
//on another io.on('connection') for the same connected client
io.on('connection', function(socket){
store(client.connectiontime);
}
How do I use the client variable only for the operations related to the currently connected client if it is considered static?
First, each socket is given a name that can be used to refer to it, but that changes each time the same client connects so this would not be useful if it is supposed to remain after the client leaves. If your goal is to store the connection time somewhere (a database?) then you would have to get a unique identifier from the client that could be used to find them again similar to a login. You would then pass the date object into the function that handles storing that time.
You should note though, that 'connection' is only called the first time the socket connects. A connection is not the event you normally would be using for when a client does something unless they disconnects between each access of the server program.
If you are sure you want to just use the Client object, you would likely have to create a client array and use the socket id as a key to access the object later. You would then have something like
array[socket.id].connectiontime = Date.now()
var client={}; //is this static across all sockets (or connected clients) that are connected?
var clients = [];
io.on('connection', function(socket){
clients[] = {
id : socket.id
connectiontime : Date.now()
}
});
//on another io.on('connection') for the same connected client
io.on('connection', function(socket){
// Here you would search for the object by socket.id and then store
store(client.connectiontime);
}

Socket.io (1.0) + Multiple client connections

So I'm connecting two variable (objects) to the same socket.io server, one's job is to handle public feed and another's to handle private feed with extended functions.
I've attempted the "force new connection" option, however both connections seem to still use utilize the same socket + session Id.
I originally didn't include code because this is so basic, but here you go:
var socket = io(host);
socket.on('connect', function(e){
socket.emit('join', {
channel: stream_channel,
});
});
One is var socket, the other is var socket2. When it connects to the server it emits "join" where:
io.on('connection', function(socket){
socket.on('join', function(d){
socket.join(d.channel);
});
});
I was able to figure this out by:
Subscribing the websocket to multiple rooms
Appending additional variables at each POST to define the room to emit to
I was able to determine that:
Utilizing the same host will always keep the same session id / socket (even with force connection enabled)
Potentially using a different host or namespace would allow a separation in connection
It's better to keep a single connection with multiple rooms

how to get number of socket connections using socket.io

Is there a way to get the number of connections in socket.io?
I want to display a message on my site that says "x users connected right now"
Basically if I did a socket.broadcast I want to count how many connections that would go to.
You can use
io.sockets.clients().length
Basically io.sockets.clients() returns Socket instances of all clients. If you're using rooms then you should better use
io.sockets.clients('room').length
because it returns socket instances of all clients in a particular room
Using this code Server site
var noOfUser=[];
socket.on('someEventFromClient',function(data){
//User name must unique
socket.username=data.username;
noOfUser.push(data.username);
//Now you can emit no of user to client are any where
console.log('NO of user:'+noOfUser.length);
});
socket.on('disconnect',function(){
for(var i=0;i<noOfUser;i++)
{
if(noOfUser[i]==socket.username)
{
noOfUser.splice(i,1);
}
//Now you can emit no of user to client are any where
console.log('NO of user:'+noOfUser.length);
}
});
Client side:
when user connect socket server emit this event
socket.emit('someEventFromCLient',{username:'someuniqueID'});

Socket.IO messaging to multiple rooms

I'm using Socket.IO in my Node Express app, and using the methods described in this excellent post to relate my socket connections and sessions. In a comment the author describes a way to send messages to a particular user (session) like this:
sio.on('connection', function (socket) {
// do all the session stuff
socket.join(socket.handshake.sessionID);
// socket.io will leave the room upon disconnect
});
app.get('/', function (req, res) {
sio.sockets.in(req.sessionID).send('Man, good to see you back!');
});
Seems like a good idea. However, in my app I will often by sending messages to multiple users at once. I'm wondering about the best way to do this in Socket.IO - essentially I need to send messages to multiple rooms with the best performance possible. Any suggestions?
Two options: use socket.io channels or socket.io namespaces. Both are documented on the socket.io website, but in short:
Using channels:
// all on the server
// on connect or message received
socket.join("channel-name");
socket.broadcast.to("channel-name").emit("message to all other users in channel");
// OR independently
io.sockets.in("channel-name").emit("message to all users in channel");
Using namespaces:
// on the client connect to namespace
io.connect("/chat/channel-name")
// on the server receive connections to namespace as normal
// broadcast to namespace
io.of("/chat/channel-name").emit("message to all users in namespace")
Because socket.io is smart enough to not actually open a second socket for additional namespaces, both methods should be comparable in efficiency.

Nodejs and socket.io selecting sockets to broadcast

I have a nodejs + socket.io solution and sockets join different rooms. How can i select sockets from different rooms to broadcast to them a certain message without using a for loop that will stall the application for all users?
The solution is simple, make every "special" user (the ones that you want to group) connect to a secret channel with Socket.IO, in your server-side code:
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
if (condition_to_determine_is_user_has_access) {
socket.join('specials');
socket.broadcast.to('specials').emit("new special user has joined");
}
});
You may also want to block access to that channel to un-allowed users, based on cookies / sessions.
Read more here: http://www.danielbaulig.de/socket-ioexpress/

Resources