How to avoid users see data from other user socket? - node.js

I have a dasboard that is making socket request every five seconds, sometimes, some users start getting data from other user socket request, but at the begging everything is working fine.
I have tried with sticky-session, diferrent socket instance, personalized socket event names.
if someone unsderstand my problem and i have a solution, i would be grateful.

Sockets are, by definition, separate from each other. I suspect the issue is that you're emitting to a namespace rather than to a particular socket.
io.of('someNamespace').emit('data');
vs
io.of('someNamespace').on('connection', (socket) => {
socket.emit('data');
});
In the first example we're sending data to all sockets in the namespace. In the second we're only sending data to a particular socket. The difference is in where you're emitting the data.

Related

why is my socket.io server assigning new socket ids to clients or losing track of existing socket ids?

I'm developing a simple website, where the client and server communicate over web sockets. I'm using nodejs and the socket.io library for the socket communication
Specifically, my server works as a middleware between an mqtt broker and my client. So on one hand, my server connects with the mqtt broker to consume messages and on the other hand delivers these messages to the connected clients over web sockets. I'm using the node mqtt library for the mqtt communication.
My codebase is fairly large, so to give you a feeling of how my code looks like, I will show this example, which should be straightforward to understand:
const io = require("socket.io")(port);
handleRequests(io) {
io.on("connection", (socket) => {
logger.info(`New client connected: ${socket.id}`);
this.clients[socket.id] = { // track clients and subscribed topics
topic: '',
};
this.numberOfUsers++;
io.sockets.emit("onUser", this.numberOfUsers);
this.handleChange(socket);
this.addToSubscribedClients(socket);
this.removeFromSubscribedClients(socket);
this.handleDisconnect(socket);
this.sendMqttMessageToClient(socket);
});
}
This is my "main" function, where as you can see, I'm initializing an io object and using it later by passing it to the handleRequests function. Each time a new client connects, I'm calling the callback function where I call the five other functions and passing the socket object as a parameter, which should be fine I guess. I'm passing the socket object as a parameter because I need it to later call socket.emit in order to send back message to a specific client, since the socket object is unique for each client.
This works great until more than ~ 30 clients are connected. I'm trying to debug this for 2 weeks now and can't figure out why this is happening. I'm testing this by opening multiple tabs in my browser. I start with one client and then increase the number of clients/tabs. At some points, I notice that some clients receive no values from the server but other clients still do, which is incorrect since all clients should receive the values in real time.
I noticed that the clients, which are not receiving values have other ids than the ones stored on the server. I tested this with a simple console.log() on both clients and server. How this is happening? I'm very positive that I'm sending the ids correctly since there are other clients, which still receive values from the server. My guess is that the server is somehow disconnecting some clients automatically, because if a client reconnects then a new id will be assigned to it automatically.
Does anyone have any idea why this is happening? and why it works fine with the first ~30 clients and starts to occur when many clients are connected? This issue is very hard to debug since the code works fine for a small number of clients and no errors are thrown when the bug occurs, so I'm hoping that someone had this before.
Edit
Now I just found that i can print a reason for socket disconnection. When I do that, ping timeout is printed, which I don't understand because when I have one single or few clients connected then this error does not happen.

Is there a possible way to restrict processing of socket emits and make delay between them?

For example: to prevent user spam in chat room, is there a socket.io server side solution that could prevent user from emitting event if 3 seconds for example haven't passed yet?
On a rough look, it seems you'd need to implement any filtering like this client-side, the docs don't seem to show any hooks for message filtering. You could have your clients send to a different channel than the one they listen to, then setup a relay on the server that listens to one channel, filters then emits to another...

socket.io room authorisation

I have a use case of socket.io where, within an individual namespace, a client can connect to several rooms. A user needs to authenticate on a per-room basis (because they may not be allowed to access those data streams).
Obviously I can check the authorisation on connection to the namespace using a middleware function and some auth data, but unless those rooms are already in socket.rooms when the connection is initiated, I do not know how to check, when a socket joins a room, whether or not it is authorised and subsequently force it to leave the room if it is not authorised.
Is there a join event or equivalent way of doing this? Like the connection event for a namespace but for a room.
EDIT
Having read through the source for socket.io, it appears that no events are triggered when a socket joins a room, but I might have misunderstood something: on reading the source of socket.io-client, joining rooms isn't inherent in the system, suggesting that this is only something that can be triggered on the server side. In that case, I'm assuming I have to manage the client's joining of rooms myself? If this is true, then I can just have something like:
socket.on('join', function(data) { ... });
so that when a socket wants to listen to a particular data stream, it just emits a "join" event, with some data on which room it wants to join, and I handle the whole thing on the server?
Joining a room can only be done on the server. The client typically sends an application-specific message to the server that indicates to your app that they want to join a specific room and then the server carries out that operation on the user's behalf if the request is valid.
So, all you have to do is route all your code on the server that could join a room through one particular function that can do whatever authentication you want to do. For example, you could simply create a function that was the only way your server code would ever put a socket into a room:
function joinAuth(socket, room) {
// can do anything you want here before actually joining the room
}

Socket.io - how to use listeners

I've looked around for an answer regarding this question, I am not sure if I am going about this the right way.
I have a node.js application that uses socket.io to push and receive data from the node server to the client. Most of the requests sent to nodejs are through HTTP Requests while the data pushed to the website is received through a socket.
I currently have unique namespaces for each of the individual listeners (for example I have a feed with comments, this means I have feed/{ID} as the listener as well as each comment has comment/{COMMENTID}. This means if there are 25 feed posts, I would have 26 (including the feed) listeners listening for the feed alone.
I am not entirely sure how socket.io pushes data through the listeners (is each listener a new socket?). In my mind, if I have a large amount of users online at one point and a single comments listener it will be hit many times with useless, unrelated data - in comparison to now where it will only receive data relevant to the user.
What is the best way to set up the listeners?
Is more or less listeners beneficial?
That's a bad way to use listener. You should use just
socket.on('feed',feed)
socket.on('comment',comment)
When you want to send data to feed listener, use "socket.emit('feed',{id:1})".
When you want to send data to comment listener, use "socket.emit('comment',{commentid:1})"
This will reduce you to just 2 listener.
You should use Rooms to handle this. Each time a user is viewing a feed page, it register to a room and then you push only the relevant information to users based on the page they are actually seeing.
socket.on('subscribe', function(data) { socket.join(data.room); });
socket.on('unsubscribe', function(data) { socket.leave(data.room); });
then when you want to send information to a specific room
io.sockets.in('feed_1').emit('comment', data);
You can see the documentation here: https://github.com/LearnBoost/socket.io/wiki/Rooms

How do I completely destroy a socket.io connection?

I'm creating a browser chat from Socket.io and Node.js. Everything has been running smoothly, but I appear to be having a problem with disconnecting sockets. When I run socket.disconnet();, the server runs the socket.on("disconnect", event, but it doesn't actually remove the socket from internal listeners.
When I run socket.disconnect(); on a socket, the socket no longer recieves any new messages, but when the "disconnected" user sends a message, the server receives and sends it back to all clients. I want to create a proper /kick command but it's difficult when I have to restructure all of my code just to accomidate for a simple function.
Commands like socket.connection.destroy();, socket.end();, and socket.transport.destroy(); are invalid and undefined. Does anyone have any suggestions? I've been working on this problem for days and I haven't found any answer other than to set a shutup boolean to the socket and tell the message event to ignore specific sockets. Is this the best way? What happens if the user starts editing javascript code and I need a way from receiving other events from a client?
Well you can see if the socket is connected or not. If socket is connected you can emit the data and vice versa. :)
Hope it helps..!
YourProject.sockets.on('connection',function(socket){
setInterval(function(){
if(!socket.disconnected){
socket.emit('entrance',{message:'Hey Bro'});
}
},10000);
});
have you tried to interrupt thread ? That should end all I/O operations with an Exception.

Resources