Design choice using node.js and express and socket.io - node.js

I want to make a web app where every user can create a chat room that other users can join. I would like to have a main node server managing the rooms, and every time a user creates a new room, a new chat server should be started by the main server and it should manage the room.
My question is, how can I make the new server start in node.js and how can I manage it?

Socket.io allows you too use the room feature and have the behavior you want (separate chat rooms) without running a separate chat server. Running a separate chat server is not really convenient in node.js because it means running another process, and it makes communication between the main server and the chat servers extra complicated.
What i would advise is using that feature and adopt the following kind of design:
io.on('connection', function(socket) {
//initialize the object representing the client
//Your client has not joined a room yet
socket.on('create_room', function(msg) {
//initalize the object representing the room
//Make the client effectively join that room, using socket.join(room_id)
}
socket.on('join_room', function(msg) {
//If the client is currently in a room, leave it using socket.leave(room_id); I am assuming for the sake of simplicity that a user can only be in a single room at all time
//Then join the new room using socket.join(room_id)
}
socket.on('chat_msg', function(msg) {
//Check if the user is in a room
//If so, send his msg to the room only using socket.broadcast.to(room_id); That way, every socket that have joined the room using socket.join(room_id) will get the message
}
}
With this design, you're simply adding listeners to event, and once set up, the whole server is running fine without having to deal with concurrency or sub processes.
It's still very minimalist and you'll probably want to handle a few more concepts, such as unique nicknames, or password authentication etc.
But that can easily be done using this design.
Have fun experimenting with socket.io and node.js!

Related

How to fire event in each 30 seconds for multiple socket rooms via nodejs

I am trying to develop quiz game in which multiple players can play quiz game with each other by making teams. For that I am using nodejs,express and socket.io for connection and for team generation and manage it I a using socket.io rooms.
My challenge is to fire an event that will show questions to teams (socket rooms) in each 30 seconds.
I have already established connection between client and server via socket.io and successfully generated teams and their respected rooms.
here is my code for connection and team generation.
Server
global.io.on('connection',function(socket){
console.log('conn establish');
socket.on('requestToPlay',function(request){
if(request.hasOwnProperty('contact_number')){
request.socket_id = socket.id;
GameController.requestToPlay(request);
}
});
socket.on('joinRoom',function(roomId){
console.log('event fired');
socket.join(roomId);
});
});
when a user will wish to play he will fire requestToPlay event and server will assign a room id with him. After that he will fire joinRoom event to join that room.
I want that when a room is created a auto generated process set to that room that will fire an event in each 30 seconds and will provide questions to client.
Is there an way to set an auto generated event on each room on their creation time that will do this.
kindly suggest any example or article link for this.
any help or suggestion is highly appreciated.
it can be done using setInterval link for ref
you can also use some API like node-schedule, node-cron

Handle chat system with socket.io, nodejs and mongodb

I have to create a chat system for our client online shop, we use nodejs/mongodb/socket.io.
I just tested if the realtime conversation between my nodejs and a simple html page is working :
const server = app.listen(app.get('port'), () => {
console.log("working");
});
var io = require('socket.io').listen(server);
io.on('connection', function(socket){
socket.on('chat message', function(msg){
console.log('message: ' + msg);
});
socket.emit('I just emit here for test', 'hello');
});
This code just working, now the fun part is to be able to make a shop manager discuss to a client, but clients shouldn't able to discuss between them (I have already a "clients" and "shop manager" collection ) like
below picture :
So, could someone tells me what is the best workflow to achieve this?, it means how to identify a client? and begin conversation to him? i am a bit lost with socket.io ...
Thanks for your help.
Create a message schema which will store conversations between client and manager.
Create a schema which will hold rooms or communication IDs.
Whenever a client logs into your system, show him the list of rooms, and when a client picks any room, show him the conversation.
Now, how to create a room?
Whenever a client wants to communicate with a manager (let's use ClientA and ManagerA), check if the conversation already exists or not. If a communication already exists, create a unique room like "clientA-room-managerA" and add both the parties to that room, store all the conversations in existing messages schema.
If the communication does not exist, create a room like "clientA-room-managerA" and then create a chat record in the schema which will hold communication Ids, and then start the room same as before "clientA-room-managerA"
By this way you should be able to create multiple chat records for a client and manager.
A client will not be able to communicate with other clients
A Manager can have communication with various clients
Consider a manager with user id: 123456789 and client with 0987654321, then you can create a room like:
var room = manager.user_id + "-room-" + client.user_id;
// room = 123456789-room-0987654321
//then join the client and manager to the room
manager_socket.join(room);
client_socket.join(room);
//you can send a message in a room:
io.sockets.in(room).emit('new_message',{"msg":"hi there"});
PS:
This is a kind of group chat where the group contains 2 members i.e. Client and a manager. For reference you can see this links:
http://psitsmike.com/2011/10/node-js-and-socket-io-multiroom-chat-tutorial/
https://github.com/jgonera/socket.io-multichat
In socket.io each socket has an individual ID which you can use to communicate between particular sockets. You can assign a particular value to the ID if you want, for example the user's MongoDB _id, for example:
this.userEmit(userID).emit('got user settings', settings);
// where userEmit is a custom function that will handle an error case when the id can't be found
You can also broadcast to specific "rooms", whereby only sockets that are members of that room will receive the message, e.g.:
io.sockets.in(groupID).emit('update group status', {
groupID: groupID,
onlineMembers: x.length
});
See their documentation for some examples: https://socket.io/docs/rooms-and-namespaces/

I can't get my head around websockets (via socket.io and node.js)

I'm new to websockets/socket.io/node.js. I'm trying to write a card game app, but pretty much all the example tutorials I've found are creating chat applications. So I'm struggling to get my head around the concepts and how they can be applied to my card game.
Keeping it simple, the card game will involve two players. The game involves moving cards around the table. Each player has to see the other player's moves as they happen (hence the need for constant connections). But the opponents cards are concealed to the other.
So two people browse to the same table then click to sit (and play, when both seats are taken). Using
io.on("connection", function(sock){
//socket events in here
});
am I creating the one socket ('io', or 'sock'?) that both clients and the server share, or is that two separate sockets (server/clientA and sever/clientB)? I ask, because I'm struggling to understand what's happening when a message is emitted and/or broadcast. If a client emits a message, is that message sent to both the server and the other client, or just the server? And then, further does it also send the message to itself as well?? It seems as though that's the logic... or what is the purpose of the 'broadcast' method?
From a functional perspective, I need the server to send different messages to each player. So it's not like a chatroom where the server sends the chat to everyone. But if it's one socket that the three of us share (clients and server), how do I manage who sees what? I've read about namespaces, but I'm struggling to work out how that could be used. And if it's two separate sockets, then I can more easily imagine sending different data to the separate clients. But how is that implemented - is that two 'io' objects, or two 'sock' objects?
Finally, I've got no idea if this is the sort of long-winded question that is accepted here, so if it's not, can someone direct me to a forum that discussions can occur? Cheers!
(in case it matters I'm also using Expressjs as the server).
Edit to add:
Part of my confusion is regarding the difference between 'io' and 'sock'. This code eg from the socket.io page is a good example of methods being applied to either of them:
io.on('connection', function(socket){
socket.emit('request', /* */); // emit an event to the socket
io.emit('broadcast', /* */); // emit an event to all connected sockets
socket.on('reply', function(){ /* */ }); // listen to the event
});
WebSocket server side listens for incoming socket connections from clients.
Each client upon connection opens its own socket between him and server. The server is the one that keeps track of all clients.
So once client emits the message server is listening for, the server can do with that message whatever. The message itself can contain information about who is the recipient of that message.
The server can pass the message to everyone or broadcast it to specific user or users based on information your client has sent you or some other logic.
For a card game:
The server listens for incoming connections. Once two clients are connected both of them should emit game ID in which they want to participate. The server can join their sockets in one game(Room) and all of the communication between those two clients can continue in that room. Each time one of the clients passes data to the server, that data should contain info about the recipient.
Here is one simple example that could maybe get you going:
Client side
// set-up a connection between the client and the server
var socket = io.connect();
// get some game identifier
var game = "thebestgameever";
socket.on('connect', function() {
// Let server know which game you want to play
socket.emit('game', game);
});
function makeAMove(move)
{
socket.emit('madeAMove', {move:move, game:game});
}
socket.on('move', function(data) {
console.log('Player made a move', data);
});
Server side
io = socketio.listen(server);
//listen for new connections from clients
io.sockets.on('connection', function(socket) {
// if client joined game get his socket assigned to the game
socket.on('game', function(game) {
socket.join(game);
});
socket.on('madeAMove', function(data){
let game = data.game;
let move = data.move;
io.sockets.in(game).emit('move', move);
});
})

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