How to create dynamic socket rooms using socket.io - javascript

I want to implement multiple chat using socket.io can, iwas able to implement one to one chat using one socket.room but i want to create multiple socket rooms to chat with multiple people parallel
below is the example i got in git but i was not able to understand that how it will work for multiple chat can any one explain
Server side
io = socketio.listen(server);
// handle incoming connections from clients
io.sockets.on('connection', function(socket) {
// once a client has connected, we expect to get a ping from them
saying what room they want to join
socket.on('room', function(room) {
socket.join(room);
});
});
// now, it's easy to send a message to just the clients in a given
room
room = "abc123";
io.sockets.in(room).emit('message', 'what is going on, party
people?');
// this message will NOT go to the client defined above
io.sockets.in('foobar').emit('message', 'anyone in this room yet?');
Client side
// set-up a connection between the client and the server
var socket = io.connect();
// let's assume that the client page, once rendered, knows what room
it wants to join
var room = "abc123";
socket.on('connect', function() {
// Connected, let's sign-up for to receive messages for this room
socket.emit('room', room);
});
socket.on('message', function(data) {
console.log('Incoming message:', data);
});

Imagine a user with multiple Chat Room to choose. When he click on a specific room he will get the information of it : in this example ChatRoom1.
The client socket (belonging to the user who has click on this room) has first to join this room
→ so that's why we have :
socket.emit(room, ChatRoom1)
// on the other part the server side will add the socket id of this client to this room :
socket.on('room', function(room) {
socket.join(room);
});
Now if you want to emit a message to all socket belonging to a specific room you use this command on the server part:
io.sockets.in(ChatRoom1).emit('message', 'what is going on, party
people?');
→ in fact this command just send a message to all socket who is belonging to ChatRoom1
→ Basically a Room is just an array of socketId
SO now on the client side you have this :
socket.on('message', function(data) {
console.log('Incoming message:', data);
});
this is just a listener, and you will get in console log :
Incoming message: what is going on, party people?
As you soon you enter in a chatRoom your socket join a room and will listen for each event until you ask the socket to leave the room
So now you can imagine that in your message you have your Id , Your Room ID and your content, when you send it the server will know where to send it.
Example:
message: {
content: 'blabla',
user: me,
date: now,
RoomId: ChatRoom1
}
On the client side each time a user send a message:
socket.emit('sendMessage', message)
On the server side:
socket.on('sendMessage', function(message){
io.sockets.in(message.RoomId).emit('message', message);
})

Related

problem in authenticated rooms in socket.io

I want to create rooms for all private chats between two connected users. I'm not getting the point how do users join the room securely.
// client side code
var socket = io.connect();
socket
.emit('Join-Room',"{\"username\": \"myusername\", \"password\" : \"mypassword\"}");
// server side code
io.sockets.on('connection', function(socket) {
socket.on('Join-Room', function(userdata) {
connection.auth(userdata,function(success){
if(success){
socket.join(username);
}
})
});
});
The problem is when the client emits a request even to join a room the credential data is received by everyone in the namespace?
What should I change to make this secure?

How do i make my chat message private?

Now my chat is working but it works like a group message as a third party will be able to see the messages. I want to make it private between two users so that when a third user log in, they will not be able to see the other users talking.
var io = socket(server);
io.on("connection", function(socket){
console.log("made socket connection", socket.id);
socket.on("chat", function(data){
var messages = {
session: data.session,
message: data.message,
sender: data.handle,
};
MsgModel.create(messages);
io.sockets.emit("chat", data);
});
socket.on("typing", function(data){
socket.broadcast.emit("typing", data);
});
});
Emit a join event from client whenever a new client joins with their userid as data. Then on server side, you can use this join event to add user to a room with its userid.
io.on('connection', function(socket){
socket.on("join", function(data){
socket.join(data.userId)
})
})
Now you have rooms with every userid and if you want to send some specific user something, you can emit to that room,
io.to(userid).emit(data)

Socket.IO clients to receive offline messages when coming back

Environment:
Nodejs+Socketio
Problem:
client A and client B both connect to server;
client B is offline;
client A sends a message to client B(client B still offline);
client B connect to server again;
[Problem] client B can't receive the message from A;
Server Code
var clients = {};
io.sockets.on('connection', function (socket) {
socket.on('online', function (data) {
if (!clients[data.username]) {
clients[data.username] = socket;
}
io.sockets.emit('message', data.user + 'online now');
});
socket.on('say', function (data) {
if (data.to == 'all') {
io.sockets.emit('message', data.message);
} else { //to specific client
clients[data.to].emit('message', data.message);
}
});
});
Description
client B connected to server at one place first.During the period of client B's offline, client A sent messages to client B. Then client B connect to server at another place again, and client B needs to receive those message from client A. How to make it work?
The amount of code I would have to write would be fairly large to create a solution if I consider which db and it's config, and client. You basically have to persist your messages in a database. As messages come in you would have to write to your conversation object (or whatever is representing the chat messages between clients).
socket.on('say', function (data) {
// pseudo code to save conversation
// var conversation = db.getConversation();
// conversation.addMessage(data.message);
// conversation.save();
if (data.to == 'all') {
io.sockets.emit('message', data.message);
} else { //to specific client
clients[data.to].emit('message', data.message);
}
});
Then you would have to get all messages from the database when a client joins.
socket.on('online', function (data) {
if (!clients[data.username]) {
clients[data.username] = socket;
}
// pseudo code to get messages and display to user on first load
// var conversation = db.getConversation();
// var messages = conversation.getLast10Messages();
// messages.forEach(function(message) {
// clients[data.username].emit('message', message);
// });
io.sockets.emit('message', data.user + 'online now');
});
use message queue like RabbitMQ. whenever a message comes from socket write to receiver's queue and when the receiver joins he will pick it from the queue.
You can specify a unique id as username to every user , save it at the server side, or use username, you also have client id(socket id), then save them in an object, now for every user you have an object that contains (username or unique id ) and socket id, now its easy to save messages when user is offline and then send it to user.
Before emitting every event, you can search for socket id in the connected sockets object of socket.if socket id exists, you can emit, else , you still have username, and you can save messages in database by username.
Remember that, you must send receiver object info(username or unique id , and socket id) in every emitting from the client

Socket.io event listening on a specific room

I'm not sure it is possible, but I really need that feature.
Can I do something like:
client side
sio = io.connect(url);
sio.to('room1').on('update', function(roomName) {
console.log(roomName);
});
Which will be triggered whenever an update event is emitted to 'room1'?
server side:
sockets.to('room1').emit('update', 'room1');
That, unfortunately, doesn't work just on the client side.
But you can do it on the server side.
Server Setup:
sockets.on('connection', function (socket) {
socket.on('join', function (room) {
socket.join(room);
});
});
//...
sockets.to('room1').emit('update', 'room1');
Client:
sio.emit('join', 'room1');
sio.on('update', function (room) {
console.log(room);
});
The "easy" way is to make sure that your emits from the server include the room in the payload.
sockets.to(room).emit('update', {room: room, message: 'hello world!'})
Most probably you want to do the same on the client-side of things.
So that the messages sent from the client to the server includes a room identifier so that the message can be routed correctly.
Or you implement name spaces.

Socket.io - send different data to sender and clients?

I am learning NodeJS and Socket.IO and have been following the various tutorials dotted about, mainly focusing on making a basic chatroom.
My app works so far: being able to send messages with clients being able to move to different "rooms".
Now I am trying to tidy it up and make it look the part.
I am stumbling with the follow idea:
When user A moves form room A to B, an emit() method is sent to update an array with a user count, which in turn is sent back to the sender. A list of rooms in a side panel is then updated e.g. Room A (0), Room B (1).
Now, emitting the new data to the sender is easy and works, the room list gets updated, and the other rooms (that the sender is not in) have hyperlinks (this is how the user moves between rooms)
But I want to send data to the other clients, so their room lists also get updated. Sending the same data as before means the other clients's rooms list is incorrect, as the data is referencing the new room name the sender joined, not the room the other client is currently in.
Some code:
socket.on('switchRoom', function(data) {
var newroom = sanitize(data).escape().trim();
socket.leave(socket.room);
socket.join(newroom);
socket.room = newroom;
socket.emit('updaterooms', rooms, newroom);
// this is the problem area, socket.room should be the socket.room data for the non-sending client
//socket.broadcast.emit('updaterooms', rooms, socket.room);
});
How would I emit to all other clients (not the sender) with the data contained in their own socket "session" (i.e. socket.room)?
You will need to emit a generated message that's catered to each socket. What you will need to do is iterate through each socket, emitting the custom message based on each socket, for example:
io.sockets.on('connect', function(socket) {
socket.on('switchRoom', function(data) {
var newroom = sanitize(data).escape().trim();
socket.leave(socket.room);
socket.join(newroom);
socket.room = newroom;
socket.emit('updaterooms', rooms, newroom);
io.sockets.clients.forEach(function(client) {
if (socket != client) {
client.emit('updaterooms', rooms, client.room);
}
});
});
});

Categories

Resources