Nodejs ZMQ monitoring sockets - node.js

I got this code for monitoring sockets in the zmq bindings for nodejs. So far it works but my problem is I dnt know what events the monitoring socket has. The code I got only did that, I will continue looking for more code but this is what I have so far..
``
var zmq = require('zmq');
var socket = zmq.socket('pub');
socket.connect('tcp://127.0.0.1:10001');
socket.monitor();
I tried adding an "onmessage" event handler but it showed nothing, so.. I dnt know whats up..
socket.on("message",function(msg){
console.log(msg);
});

I printed the object that I got back from the monitor() function and from it I was able to get some monitor events, I think it is unelegant though, I got this link that tests the monitor function of the socket ( https://github.com/JustinTulloss/zeromq.node/blob/master/test/socket.monitor.js ) but some things are not working but...
mon.monitor();
console.log(mon);
mon.on("message",function(msg){
console.log(msg);
});
mon.on('close',function(){console.log("Closed");});
mon._zmq.onMonitorEvent = function(evt){
if (evt == 1)
console.log("Should be 1 : "+ evt);
else
console.log(evt);
};

I haven't worked with the PUB/SUB handlers in 0mq. I have used some of the other types and am fairly familiar. Having not tested this code, my recommendation would be
SCRIPT 1: Your existing PUB script, needs to send a message
socket.send('TEST_MESSAGES', 'BLAH')
SCRIPT 2: This needs to be added:
var zmq = require('zmq');
var sub_socket = zmq.socket('sub');
sub_socket.connect('tcp://127.0.0.1:10001');
sub_socket.subscribe('TEST_MESSAGES')
sub_socket.on("message",function(msg){
console.log(msg);
});
The trick here is timing. 0mq doesn't give you retries or durable messages. You need to build those elements on your own. Still if you put your publish in a timer (for the sake of getting an example running) you should see the messages move.

Related

socket.on event gets triggered multiple times

var express = require('express');
var app = express();
var server = app.listen(3000);
var replyFromBot;
app.use(express.static('public'));
var socket = require('socket.io');
var io = socket(server);
io.sockets.on('connection' , newConnection);
function newConnection(socket) {
console.log(socket.id);
listen = true;
socket.on('Quest' ,reply);
function reply(data) {
replyFromBot = bot.reply("local-user", data);
console.log(socket.id+ " "+replyFromBot);
socket.emit('Ans' , replyFromBot);
}
}
i've created a server based chat-bot application using node.js socket.io and express but the thing is for first time when i call socket.on it gets executed once and for 2nd time it gets executed twice for 3rd thrice and so on i've tackled this issue by setting a flag on my client so that it would display only once. i just wants to know is my code logically correct i mean is this a good code? because if the client ask a question for 10th time than listeners array will have 10+9+8....+1 listeners it would go on increasing depending upon number of questions clients asked. which is not good
i tried using removeListener it just removes listener once and it dosent call back for 2nd time. what do you guys recommend? do i go with this or is there any other way to add the listener when socket.on called and remove it when it gets executed and again add listener for the next time it gets called
thank-you.
client code:
function reply() {
socket.emit('Quest' , Quest);
flag = true;
audio.play();
socket.on('Ans', function(replyFromBot) {
if(flag) {
console.log("hi");
var para = document.createElement("p2");
x = document.getElementById("MiddleBox");
para.appendChild(document.createTextNode(replyFromBot));
x.appendChild(para);
x.scrollTop = x.scrollHeight;
flag = false;
}
});
}
The problem is caused by your client code. Each time you call the reply() function in the client you set up an additional socket.on('Ans', ...) event handler which means they accumulate. You can change that to socket.once() and it will remove itself each time after it get the Ans message. You can then also remove your flag variable.
function reply() {
socket.emit('Quest' , Quest);
audio.play();
// change this to .once()
socket.once('Ans', function(replyFromBot) {
console.log("hi");
var para = document.createElement("p2");
x = document.getElementById("MiddleBox");
para.appendChild(document.createTextNode(replyFromBot));
x.appendChild(para);
x.scrollTop = x.scrollHeight;
});
}
Socket.io is not really built as a request/response system which is what you are trying to use it as. An even better way to implement this would be to use the ack capability that socket.io has so you can get a direct response back to your Quest message you send.
You also need to fix your shared variables replyFromBot and listen on your server because those are concurrency problems waiting to happen as soon as you have multiple users using your server.
Better Solution
A better solution would be to use the ack capability that socket.io has to get a direct response to a message you sent. To do that, you'd change your server to this:
function newConnection(socket) {
console.log(socket.id);
socket.on('Quest', function(data, fn) {
let replyFromBot = bot.reply("local-user", data);
console.log(socket.id+ " "+replyFromBot);
// send ack response
fn(replyFromBot);
});
}
And, change your client code to this:
function reply() {
audio.play();
socket.emit('Quest', Quest, function(replyFromBot) {
console.log("hi");
var para = document.createElement("p2");
x = document.getElementById("MiddleBox");
para.appendChild(document.createTextNode(replyFromBot));
x.appendChild(para);
x.scrollTop = x.scrollHeight;
});
}
Doing it this way, you're hooking into a direct reply from the message so it works as request/response much better than the way you were doing it.
Instead of socket.on('Quest' ,reply); try socket.once('Quest' ,reply);
The bug in your code is that each time newConnection() is called node registers a event listener 'Quest'. So first time newConnection() is called the number of event listener with event 'Quest' is one, the second time function is called, number of event listener increases to two and so on
socket.once() ensures that number of event listener bound to socket with event 'Quest' registered is exactly one

publisher subscriber pattern of zmq is not working as expected

I have simple sample program for pub/sub pattern in nodejs which is as shown below
publisher.js
var zmq = require('zmq');
var pub = zmq.socket('pub');
pub.bind('tcp://127.0.0.1:6666');
console.log("Current 0MQ version is " + zmq.version);
var loop =0
pub.send(['t',loop++ + ' pub msg']);
pub.send(['t',loop++ + ' pub msg']);
subber.js
var zmq = require('zmq');
var sub = zmq.socket('sub');
sub.connect('tcp://127.0.0.1:6666');
sub.subscribe('t'); //herein lies the question
console.log('Received msg:');
sub.on('message',function(topic, msg){
console.log('Received msg:',msg.toString());
})
there are some unexpected behaviour which i am falling to understand from two days
1:for the first time when i run subber.js first and then
publisher.js i will get the messages as expected
2:Again if i run in the same order i am not getting any messages (subber.js and publisher.js)
3: for first i run publisher.js and then subber.js none of the messages i will get
really i am not understanding that sample program working or not please help me to understand publisher subscriber pattern of zmq with some sample code (**In the sample i have not used setinterval bcoz once the publisher send the message i have send to subscriber please provide the some sample to understand and accomplish this)
Thanks
When you start publisher first, publisher send msg (in nothing) so when subber starts, it can't get any msg.
First of all. You should use sync bind. Socket not created yet, but you already try to send something.
pub.bindSync('tcp://127.0.0.1:6666');
Nevertheless it didn't help me. I think bindSync work not sync (((. So I have to use timer to send something if application starts.
setTimeout( () => {
pub.send(['t',loop++ + ' pub msg']);
pub.send(['t',loop++ + ' pub msg']);
}, 1000);

Socket.IO server throttling a fast client

I have a server that uses socket.io and I need a way of throttling a client that is sending the server data too quickly. The server exposes both a TCP interface and a socket.io interface - with the TCP server (from the net module) I can use socket.pause() and socket.resume(), and this effectively throttles the client. But with socket.io's socket class there are no pause() and resume() methods.
What would be the easiest way of getting feedback to a client that it is overwhelming the server and needs to slow down? I liked socket.pause() and socket.resume() because it didn't require any additional code on the client-side - backup the TCP socket and things naturally slow down. Any equivalent for socket.io?
Update: I provide an API to interact with the server (there is currently a python version which runs over TCP and a JavaScript version which uses socket.io). So I don't have any real control over what the client does. Which is why using socket.pause() and socket.resume() is so great - backing up the TCP stream slows the python client down no matter what it tries to do. I'm looking for an equivalent for a JavaScript client.
With enough digging I found this:
this.manager.transports[this.id].socket.pause();
and
this.manager.transports[this.id].socket.resume();
Granted this probably won't work if the socket.io connection isn't a web sockets connection, and may break in a future update, but for now I'm going to go with it. When I get some time in the future I'll probably change it to the QUOTA_EXCEEDED solution that Pascal proposed.
Here is a dirty way to achieve throttling. Although this is a old post; some people may benefit from it:
First register a middleware:
io.on("connection", function (socket) {
socket.use(function (packet, next) {
if (throttler.canBeServed(socket, packet)) {
next();
}
});
//You other code ..
});
canBeServed is a simple throttler as seen below:
function canBeServed(socket, packet) {
if (socket.markedForDisconnect) {
return false;
}
var previous = socket.lastAccess;
var now = Date.now();
if (previous) {
var diff = now - previous;
//Check diff and disconnect if needed.
if (diff < 50) {
socket.markedForDisconnect = true;
setTimeout(function () {
socket.disconnect(true);
}, 1000);
return false;
}
}
socket.lastAccess = now;
return true;
}
You can use process.hrtime() instead of Date.time().
If you have a callback on your server somewhere which normally sends back the response to your client, you could try and change it like this:
before:
var respond = function (res, callback) {
res.send(data);
};
after
var respond = function (res, callback) {
setTimeout(function(){
res.send(data);
}, 500); // or whatever delay you want.
};
Looks like you should slow down your clients. If one client can send too fast for your server to keep up, this is not going to go very well with 100s of clients.
One way to do this would be have the client wait for the reply for each emit before emitting anything else. This way the server can control how fast the client can send by only answering when ready for example, or only answer after a set time.
If this is not enough, when a client exceeded x requests per second, start replying with something like QUOTA_EXCEEDED error, and ignore the data they send in. This will force external developers to make their app behave as you want them to do.
As another suggestion, I would propose a solution like this:
It is common for MySQL to get a large amount of requests which would take longer time to apply than the rate the requests coming in.
The server can record the requests in a table in db assuming this action is fast enough for the rate the requests are coming in and then process the queue at a normal rate for the server to sustain. This buffer system will allow the server to run slow but still process all the requests.
But if you want something sequential, then the request callback should be verified before the client can send another request. In this case, there should be a server ready flag. If the client is sending request while the flag is still red, then there can be a message telling the client to slow down.
simply wrap your client emitter into a function like below
let emit_live_users = throttle(function () {
socket.emit("event", "some_data");
}, 2000);
using use a throttle function like below
function throttle(fn, threshold) {
threshold = threshold || 250;
var last, deferTimer;
return function() {
var now = +new Date, args = arguments;
if(last && now < last + threshold) {
clearTimeout(deferTimer);
deferTimer = setTimeout(function() {
last = now;
fn.apply(this, args);
}, threshold);
} else {
last = now;
fn.apply(this, args);
}
}
}

nodeJS zeroMQ: why cant send message if sock.send not in setInterval

I was using zeroMQ in nodeJS. But it seems that while sending the data from producer to worker, if I do not put it in setInterval, then it does not send the data to the worker. My example code is as follows:
producer.js
===========
var zmq = require('zmq')
, sock = zmq.socket('push');
sock.bindSync('tcp://127.0.0.1:3000');
console.log('Producer bound to port 3000');
//sock.send("hello");
var i = 0;
//1. var timer = setInterval(function() {
var str = "hello";
console.log('sending work', str, i++);
sock.send(str);
//2. clearTimeout(timer);
//3. }, 150);
sock.on('message', function(msg) {
console.log("Got A message, [%s], [%s]", msg);
});
So in the above code, if I add back the lines commented in 1, 2 and 3, then I do receive the message to the worker side, else it does not work.
Can anyone throw light why to send message I need to put it in setInterval? Or am I doing something wrong way?
The problem is hidden in the zmq bindings for node.js . I've just spent some time digging into it and it basically does this on send():
Enqueue the message
Flush buffers
Now the problem is in the flushing part, because it does
Check if the output socket is ready, otherwise return
Flush the enqueued messages
In your code, because you call bind and immediately send, there is no worker connected at the moment of the call, because they simply didn't have enough time to notice. So the message is enqueued and we are waiting for some workers to appear. Now the interesting part - where do we check for new workers? In the send function itself! So unless we call send() later, when there are actually some workers connected, our messages are never flushed and they are enqueued forever. And that is why setInterval works, because workers have enough time to notice and connect and you periodically check if there are any.
You can find the interesting part at https://github.com/JustinTulloss/zeromq.node/blob/master/lib/index.js#L277 .
Cheers ;-)

How can i handle Close event in Socket.io?

I'm making simple online game which based on Web.
the game uses Socket.io for netwoking each other.
but I encountered the problem.
think about following situation .
I ran Socket.io server.
one player making the room , and other player join the room.
they played game some time ..
but one player so angry and close the game tab.
in this situation , how can I get the event which one client have been closed the browser in server-side ?
according to googling , peoples say like this : "use browser-close event like onBeforeUnload"
but I know that All browser don't support onBeforeUnload event. so i want solution about
checking the client disconnection event in SERVER SIDE.
in Socket.io ( nodeJS ) server-side console , when client's connection closed , the console say like following :
debug - discarding transport
My nodeJS version is 0.4.10 and Socket.io version is 0.8.7. and both are running on Linux.
Anyone can help please ?
shortend codes are here :
var io = require ( "socket.io" ).listen ( 3335 );
io.sockets.on ( "connection" , function ( socket )
{
socket.on ( "req_create_room" , function ( roomId )
{
var socketInstance = io
.of ( "/" + roomId )
.on ( "connection" , function ( sock )
{
sock.on ( "disconnect" , function ()
{
// i want this socket data always displayed...
// but first-connected-client doesn't fire this event ..
console.log ( sock );
}
});
});
});
Update: I created a blog post for this solution. Any feedback is welcome!
I recommend using the 'sync disconnect on unload' option for Socket IO. I was having similar problems, and this really helped me out.
On the client:
var socket = io.connect(<your_url>, {
'sync disconnect on unload': true });
No need to wire in any unload or beforeunload events. Tried this out in several browsers, and its worked perfectly so far.
There's an event disconnect which fires whenever a socket.io connection dies (note that you need this, because you may still have a wep page open, but what if your internet connection dies?). Try this:
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
socket.on('disconnect', function () {
io.sockets.emit('user disconnected');
});
});
at your server. Taken from Socket.IO website.
//EDIT
So I looked at your code and did some tests at my place. I obtained the very same results as you and here's my explanation. You are trying to make Socket.IO very dynamic by dynamically forcing it to listen to different urls (which are added at runtime). But when the first connection is made, at that moment the server does not listen to the other url. It seems that exactly at that point (when connection is accepted) the disconnect handler is set for the first connection and it is not updated later (note that Socket.IO does not create new connections when you call io.connect many times at the client side). All in all this seems to be a bug! Or perhaps there is some fancy explanation why this behaviour should be as it is but I do not know it.
Let me tell you some other things. First of all this dynamical creation of listeners does not seem to be a good way. In my opinion you should do the following: store the existing rooms and use one url for all of them. Hold the ID of a room and when you emit for example message event from client add the ID of a room to the data and handle this with one message handler at the server. I think you get the idea. Push the dynamic part into the data, not urls. But I might be wrong, at least that's my opinion.
Another thing is that the code you wrote seems to be bad. Note that running .on('connection', handler) many times will make it fire many times. Handlers stack one onto another, they do not replace each other. So this is how I would implement this:
var io = require("socket.io").listen(app);
var roomIds = [];
function update_listeners(id) {
io.of("/"+id).on("connection", function(socket) {
console.log("I'm in room " + id);
socket.on("disconnect", function(s) {
console.log("Disconnected from " + roomId);
});
});
}
var test = io.sockets.on("connection", function(socket) {
console.log("I'm in global connection handler");
socket.on("req_create_room", function(data) {
if (roomIds.indexOf(data.roomId) == -1 ) {
roomIds.push(data.roomId);
update_listeners(data.roomId);
}
test.emit("room_created", {ok:true});
});
socket.on("disconnect", function(s) {
console.log("Disconnected from global handler");
});
});
Keep in mind that the problem with creating connections before the listeners are defined will still occure.

Resources