Socket.io - how to use listeners - node.js

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

Related

How to avoid users see data from other user socket?

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.

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...

node.js net module pings and messages not happening

I have two node.js applications running side by side on my server and I wan't to send server-side messages between them in a light weight manner using native node.js (v0.10.33) module net
I intend the first application to send messages to the second. I see the console log listening...,
In the first application:
var push='';
var net=require('net');
var server=net.createServer(function(p){
p.on('error',function(err){console.log(err);});
push=p;
setInterval(function(){push.write(JSON.stringify({'f':'ping','data':'stay alive'}));},1000);
});
server.listen(8008,function(){console.log('listening...')});
//a real message might be sent later in the application (this example would need a setTimeout)
push.write(JSON.stringify({'f':'msg','data':'Hello World'}));
In the second application I see the console log open
var net=require('net');
var pull=new net.Socket();
pull.connect(8008,'127.0.0.1',function(){console.log('open');
pull.on('data',function(_){
_=JSON.parse(_);
if(_.f==='ping'){console.log('!!!ping!!!');}
else{console.log(_.data);}
});
pull.on('error',function(err){console.log('pull: '+err);});
});
I do not see any other activity though (no pings, and later after the open event, no hello world) and no errors.
If I inspect with console.dir(pull) I don't see events for accepting data ie: ondata or onmessage
What is wrong?
Unfortunately, I must point out that this messaging scheme is fundamentally broken. You're using TCP, which provides a stream of bytes, not messages.
Despite the fact that TCP sends its data over IP packets, TCP is not a packet protocol. A TCP socket is simply a stream of data. Thus, it is incorrect to view the data event as a logical message. In other words, one socket.write on one end does not equate to a single data event on the other. A single data event might contain multiple messages, a single message, or only part of a message.
The good news is this is a problem already solved many times over. I'd recommend either:
Using a library meant for passing JSON messages over TCP.
Using something like redis as a pub-sub messaging solution (this option makes your app much easier to scale)
If you know that your two apps will always run on the same machine, you should use node's built-in IPC mechanism.

How to send real time notification to single user using node.js and PHP

I am trying to integrate real time notifications with Node and socket.io in a Symfony Application. I have read a lot of information about this topic and have a working Node application.
nodeClient.js
var socket = io.connect( 'http://192.168.15.106:8080' );
$('a.sendSmile').click(function(){
socket.emit( 'message', { name: 'something' } );
});
socket.on('message', function(data){
console.log(data.name);
});
The problem now is with the above which is working perfectly I am able to send real time notification to all the users at once. But what's the best way to target a single user?
For example a user can send a smile to another user so only the second user should receive the notification and not all the users.
Should I make multiple listeners for node? or any other method to do this?
You need some way of identifying which socket that connected to your server is the one you want to send data to and then you can send to just that socket. You can keep track of user names when users connect or if you have some auth system, you can keep track of which socket belongs to which authenticated user.
Your server holds a list of connected sockets. Each connected one at a time and triggered a connection event on your server when they connected. Your application needs to create a way of knowing which of those connected sockets you want to send the data to. This is not something you've described anything about how you want that to work so we can't really help more specifically.
You can dispatch a notification to single user if you can discriminate that user. For example you can get a user_id on client connection to your nodejs server (the user_id is send from client, inside message) and save it in a key-value store (like Redis, memcache, ...). In this way you can correctly dispatch the notification, arrived from the server (like Symfony2 application), to right user.
I suggest you use Redis, both as a key-value store and for its implementation pattern of the publish/subscribe usable as a channel of communication between the server and the application of realtime.

Is it ok to use many socket.io events?

In socket.io for node.js you create events using:
socket.on('my event', function (data) {...});
In my case I may need to use a lot of different events (close to a 100), so I'm wondering if each of these events creates a separate listener for each client socket and would take more resources than just having a single event that receives an object that contains and identifier on which I can use switch for the events I require. Which option would be better?
They will not create new sockets for each event, you can send as many events as you want. When the socket packet goes down the wire, the event name is just a text property.
If you use your own event-name system, then you will probably just be rewriting the one already there.
There should not be an issue having over 100 events for a socket.io connection.
Each even does not create a new connection, so there should not be a "too many connections" issue.

Resources