Socket.io: Emit to specified Clients - javascript

I have a node.js/socket.io webapp that is currently working correctly polling an API and populating the html page with the emitted results.
My problem is that multiple people need to use this and I would like to separate their instances so that each person will only receive the results of their query.
Right now, when anyone uses the site it will return results of another user that may be also using the site.
I have tried to get around this using this method:
var clients = {};
io.sockets.on('connection', function(socket){
console.log("this is "+socket.id);
clients.id = socket.id;
})
io.sockets.socket(clients.id).emit('progress',{info:listing});
Of course this gets replaced with each new user that logs into the site so then everything that was emitted to the original user is now being emitted to the new user.
What I want to know is if there is any built-in function to get around this or if I should proceed with another persistent store.
Any help would be greatly appreciated.
Edit
By storing the socket object in the express.sessionStore instead of just in the program.
io.sockets.on(function(socket){
request.sessionStore.socket = socket;
})
The above code now works and only emits to the event originator.

This looks like it's been answered in another thread. The idea is to create an array of clients, and associated it to some type of client/user identification, like an ID or name.
Sending a message to a client via its socket.id

Related

How to establish a communication between two users, if the id generated by the socketIO are auto generated?

Hello I hope you are very well, I would like to ask you a question that I have not been able to deduce the answer to.
In a course I was seeing that to send a message to a specific user with socketIO.js the to () method is used and the id as a parameter, but I have a doubt, that id is auto generated by socketIO as far as I understand, so I would like to know How can the frontend know that id? The example that I saw in the course does it from the console and sends it directly to the method with the id that it already knows, then that example is not so real, what I would like to know in itself How is it that it performs a one-to-one chat if the id is autogenerated by the socket? I don't know if I understand.
For example, to start a conversation with another user, you can click on a button, trigger an event that makes emit, send the id of the user who writes, the event that should trigger the backend with socket, but my question is how does it taste like who send the message? How do you know the id of who is being sent to when establishing communication between 2 users for the first time? Obviously this must be sent by frontent as a parameter but also how does the frontend give this id of who will it be sent to? I don't know if you can store a fixed socket id for a user in a DB or Can you use your DB id to use with sockets? more than everything is what I can not deduce how it would be done?
I do not know if I understood with the question, more than everything is that, I do not know how it obtains or assigns the id for the target from where the message is sent and if this can be fixed and stored in db or is there any method to this.
I thank you in advance for your response, and any resources that you share with me about it or if you recommend a course with, I would greatly appreciate it.
as an example I have this method
io.on('connection', (client) => {
client.on('privateMessage', (data)=>{
const person = user.getPersona(client.id) //get this
client.broadcast.to(data.para).emit('privateMessage', createMsj( person.name, data.messages));
});
}
But where does the front-end of the person to receive the message to pass it to the method?
The front-end will not know the socket.io id of any other clients. This is where your server needs to be involved.
Each of your users presumably has some username that is displayed in the client UI and this is the name that other clients would know them by.
So, your server needs to keep a mapping between username and socket.io clientID. So, a user can send a request to your server to connect to BobS. Your server then needs to be able to look up BobS, find out if that user is currently connected and, if they are, then what is their socket.id value. That way, your server can facilitate connecting the two users.
This mapping would not typically be kept in a permanent store (such as a database) because the socket.id is a transient value and is only good for the duration of that client's socket.io connection. As such, it is more typically just kept in some sort of Javascript data structure (such as a Map object).

socket connection in node js

I have just started working on node js.I have been trying to make chat application using node js. In which a single user can logged in through multiple devices or browsers. If I am not wrong and as I understand each of the browser communicates with different port address since socket connection is defined by IP address and port address hence when the same user logs in from two different browsers server creates two different socket Id.Now I verify if the user is already connected by checking the parameter send to socket info.Then if the user is already connected or the socket is already set for the user then I create connection to change the socket id to previous socket id as .
io.on('connection', function(socket){
socket.id = k;
});
where k is the socket id of previously connected same user
Now when any other client emits message to the current user then Is the socket id is replaced and only one browser gets message or both of them gets message. Is the connection of server is set for both browser or a single browser. Please help me for this. I am still not clear about how socket connection establishes between client and server.
Please improve if I am doing any supposition wrongly Or how do I solve the following scenerio.
Thanks in advance
If I understand your problem correctly, let me try explain in my way. Lets say you have the following code for the server:
var io = require('socket.io')(somePort); //same port for the client to connect, e.g. 3000
io.on('connection', function(socket){
// in here you should define any actions on your primary socket
// for example:
socket.on("hello", function(dataUserSendsWithTopicHello){// overly long variable name to show my point! :)
// do something with hello data
});
// this will go to anyone who is connected and has a handler like above for "hello"
socket.emit("hello", "hello to all who listen to hello topic");
});
A corresponding client would be:
var socket = io.connect('ip:port'); // e.g. localhost:3000 - same ip and port as above
socket.on('hello', function(serverResponseToHello){
// do something when server sends back something on hello
});
// send a hello to the server
socket.emit("hello", "Sending hello to server");
Now if you want to reply to one user only, or a group of people to see some message all together, like in a chat, you could leverage socket.io's room/ namespace implementation (http://socket.io/docs/rooms-and-namespaces/) and create one room for each client, or one room for a group of clients. For this, take a look at this answer: Using Socket.io with multiple clients connecting to same server
To sum it up, there is one ip and one port. Everyone listens to this ip and port and if you open three tabs and you have some implementation like the above, all tabs will be listening to "hello". Using rooms you can group your users and isolate communication so that only the users that the communication is done between the correct users and not all.
Good luck!
I too am fairly new to Sockets (and JS), and I'm trying to make a chat app too but a little differently.
As far as i understand the message will be received only on one browser. A better design would be to let the user connect through multiple browsers/devices. You can maintain a list of all the sockets a user has connected from (if you need it).
If you need a one-to-one chat, maybe you can write some code wherein all sockets the two users connect from are joined into a single room.
socket.room = roomname
socket.join(roomname)
Then you just broadcast the message to that room. That way every sockets both users have connected to will get the message.
socket.to(socket.room).broadcast.emit("message", message);
(I am saving the room info in socket, no idea if that is a good design)
Hope this helps!

Node js connecting two socket so that retrieving would be easier

Currently now i am using io.emit where i send the event to all the connected users and in client side i check whether the id of user i emit is equal to the id of client side then the condition runs i thinks its making my code messy and bit slow is there anything i can do like connecting then in one group so when retrieving them i would be easier for me.
//server side
var id = 1;
io.emit('check',id);
// on client side
socket.on('check',function(data){
var current_user_login = //getting current user login id by php
if(data == current_user_login) {
//run some code
}
});
If you want to put certain sockets in the same room, so that it's easy
to broadcast to all of them together. Try this:
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
socket.join('group');
socket.broadcast.to('group').emit('new member');
});
Hope this helps.
The better way to solve this problem is to create an association between the user you want to send the data to and that user's socket so you can .emit() only to that particular socket. This is much, much more efficient than sending to everyone especially when you have lots of connected sockets.
You would have to explain to us much more about how you know which socket or user you want to send to in order for us to help figure out how to do that association in your server.
socket.io has the concept of "rooms" which are groups of sockets that makes it easy for you to place a socket in a specific group and to then broadcast to a specific group of sockets.
Or, each socket has an id and each socket has access to the cookies that were present when the connection was first made, both of which can sometimes be used to identify which user you want to send to. But, you'd have to explain how you know which user you want to send to for us to help give you an idea how to code that into your server.

How should I manage in-memory data in Node?

I have a simple app built using Node, Express, and Socket.io on the server side. My page queries my API when it needs to retrieve data that will not change, and uses WebSockets for getting live updates from the server for dynamic data. The app allows a single person, the "Supervisor", to send questions to any number of "Users" (unauthenticated) and view their answers as they trickle in. The Users send their data to the server using a POST request, and it is streamed to the Supervisor over a WebSocket. The server stores user data in a simple array, and uses an ES6 map of the items in the array (users) to objects containing each their questions and answers, like this:
class User {}
let users = [], qa = new Map();
io.on('connection', socket => {
let user = new User(socket.id);
users.push(user);
qa.set(user, {});
socket.on('question-answered', ({id, answer}) => {
let questionData = qa.get(user);
questionData[id] = answer;
qa.set(user, questionData);
});
});
This is obviously a very primitive way of handling data, but I don't see the need for additional complexity. The data doesn't need to persist across server crashes or restarts (the user's questions and answers are also stored in localStorage), and MongoDB and even Redis just seem like overkill for this kind of data.
So my question is, am I going about this the right way? Are there any points I'm missing? I just want a simple way to store data in memory and be able to access it through client-side GET requests and socket.io. Thank you for any help.
If an array and a map provide you the type of access you need to the data and you don't need crash persistence and you have an appropriate amount of memory to hold the amount of data, then you're done.
There is no need for more than that unless your needs (query, persistence, performance, multi-user, crash recovery, backup, etc...) require something more complicated. A simple cliche applies here: If it ain't broke, it don't need fixing.

Saving socket.io data per client

How would you save data on Socket.io per client? I've thought of this, however as I'm reading it's probably invalid:
io.on('connection', function(socket) {
console.log('socket connected');
var user = {};
//do stuff with user.
});
Does this work normally, or would it mix if somebody else joins? If it doesn't work like it should, then which way does?
What you have creates a closure for each separate connection so it works fine for per socket data that you want to keep in memory. You would then need to put all other socket communication inside that same closure so that it can access the data too. The downside to this is that it's hard to get to the data from the outside (which is sometimes required, but sometimes not).
One downside of doing it this way is that the data is temporal and will not last beyond the current connection. If there's any sort of connectivity or client hiccup and the socket.io connected is dropped and reconnects, then a new closure on behalf of the new connection will be created and the original one will be garbage collected when the socket is closed.
Another way that this is sometimes done is to use the socket.id as an index into a shared data structure, or if you use any sort of authentication with a userID to use that id as the index into a shared data structure.

Categories

Resources