Close mubsub client after emitting with socket.io-mongodb-emitter - javascript

I'm trying to emit some message into a socket.io room using socket.io-mongodb-emitter. My problem is that, my script never exists, because it keeps a connection alive to mongodb.
Please check my examples below, and give me some advice, how can I make the script close mongodb connection and let itself exit.
emitter.js this script emits the message, the client gets it, but the process doesn't exit.
var io = require('socket.io-mongodb-emitter')("mongodb://localhost:27017/test");
io.in('someRoom').emit('someMessage');
emitter-2.js this script exits, but the client never gets the message.
var io = require('socket.io-mongodb-emitter')("mongodb://localhost:27017/test");
io.in('someRoom').emit('someMessage');
io.client.close();
emitter-3.js this one works perfectly, the client gets the message, and the process exits. But setTimeout is an extremely bad solution, there must be some proper way to let this process exit by itself.
var io = require('socket.io-mongodb-emitter')("mongodb://localhost:27017/test");
io.in('someRoom').emit('someMessage');
setTimeout(function () {
io.client.close();
},100);

Maybe use a callback to get an acknowledgement that the client received the message, then call the close function
server:
var message = "hello";
io.in('someRoom').emit('someMessage', message, function(data){
console.log(data);
io.client.close();
});
client:
socket.on('someMessage', function(message, callback){
// do something with message here
callback('message received');
});

You need to use the .emit's ability to receive an acknowledgement that the message was sent.
Do like so:
io.in('someRoom').emit('someMessage',function(){
console.log('message was sent');
io.client.close();
);
On Server you need to call the function when it is received.
socket.on('someMessage', function (name, fn) {
fn('received');
});
Documentation here

Related

Socket.io—about socket disconnect

I have this scenario with socket.io:
I want to receive the data from a sever and Forward the data to webclient.But when I receive a lot of data and close the page, it console
DISCONNECTED FROM CLIENT
DISCONNECTED FROM CLIENT
DISCONNECTED FROM CLIENT
DISCONNECTED FROM CLIENT
DISCONNECTED FROM CLIENT
DISCONNECTED FROM CLIENT
DISCONNECTED FROM CLIENT
...(a lot)
Here is the code:
server:
var express=require('express');
var app=express();
var net=require('net');
var http=require('http').createServer(app);
var io=require('socket.io')(http);
var net=require('net');
var nodeServer = new net.Socket();
var aSocket=null;
io.on('connection', function (socketIO) {
aSocket=socketIO;
};
nodeServer.on('data', function(data) {
if(aSocket!=null){
aSocket.emit('pushToWebClient',useData);
aSocket.on('disconnect', function () {
console.log('DISCONNECTED FROM CLIENT');
});
}
client:
socket.on('pushToWebClient', function (useData) {
});
I find
aSocket.on('disconnect', function () {
console.log('DISCONNECTED FROM CLIENT');
});
console a lot of'DISCONNECTED FROM CLIENT' but actually it should console just once in the code.
I had even console.log(aSocket.id),it console just only one.
I don't know why it is console so many times.
I haved used setMaxListeners(10) to try to avoid it .
Will it lead to a memory leak?
It appears that you are registering multiple event listeners for the same disconnect event. In this code:
nodeServer.on('data', function(data) {
if(aSocket!=null){
aSocket.emit('pushToWebClient',useData);
aSocket.on('disconnect', function () {
console.log('DISCONNECTED FROM CLIENT');
});
}
You appear to be registering a new disconnect event listener every time you get a data message. So, if you have multiple listeners, then each one will get called when the socket disconnects and the result is that you will log the same message multiple times all for the same socket.
You can verify this is what is happening by moving your disconnect handler into the connection handler so it is only ever attached just once for each socket.
In addition putting asocket into a global or module-level variable means that your server code would only ever work with one single client at a time. It is not clear exactly what you are trying to do when you get data on the nodeserver connection - whether you're trying to send that data to only one specific client or to all connected clients.
I try to delete the code:
aSocket.on('disconnect', function () {
console.log('DISCONNECTED FROM CLIENT');
});
or moving it out of nodeServer handler,
it turn into normal and never suggest me to setMaxlisener.
I think maybe it is incorrect put one API into a API
And the envent maybe not release the socket,so it console multiple times .
EDIT: I'm moving this to the top because I saw that someone already provided my solution but you were having a problem managing the data sent to the client. Your aSocket variable will be overwritten by every new client that connects to your app. If you want to send data to a specific client using your server nodeServer, you should create a global variable (an array) that keeps track of all of your client socket connections. So instead of using one global variable aSocket do the following:
var net=require('net');
var nodeServer = new net.Socket();
var clients = [];
io.on('connection', function (socketIO) {
clients.push(socketIO);
var clientNum = clients.length-1;
aSocket.on('disconnect', function () {
clients.splice(clientNum, 1);
console.log('DISCONNECTED FROM CLIENT: '+socketIO.id);
});
};
nodeServer.on('data', function(data) {
//have your data object contain an identifier for the client that caused the handler to fire
//for the sake of the answer I just use data.id
var clientID = data.id;
if(clients[clientID]!=null){
clients[clientID].emit('pushToWebClient', useData);
}
}
Let me know how it goes! My original answer is below:
Try moving
aSocket.on('disconnect', function () {
console.log('DISCONNECTED FROM CLIENT');
});
out of your nodeServer.on('data', ...) event listener into the io.on('connection', ...) event listener like so:
io.on('connection', function (socketIO) {
aSocket=socketIO;
aSocket.on('disconnect', function () {
console.log('DISCONNECTED FROM CLIENT');
});
};
socket.io is designed to keep polling for the presence of the server/client. If either the server or the client are disconnected, the remaining 'side' continues to receive polling requests and, consequently, will continuously print an error.
You can see this effect on the client side in your browser when you disconnect your server and leave the client page open. If you look at the browser's error/console log what you should see is a continuous stream of net::ERR_CONNECTION_REFUSED errors. By placing the disconnect event handler in the .on('data', ...) handler for your server, you are seeing the converse of this situation.
net:ERR_CONNECTION_REFUSED example
This is basic code for socket.io
The following example attaches socket.io to a plain Node.JS HTTP
server listening on port 3000.
var server = require('http').createServer();
var io = require('socket.io')(server);
io.on('connection', function(client){
client.on('event', function(data){});
client.on('disconnect', function(){});
});
server.listen(3000);
I think, you should try.

Cannot emit socket message from client

So, I'm setting up an express app, with all the usual goodies like passport, mongoose, connect-flash etc, and I'm using socket.io to listen for and emit messages.
Currently, I'm just emitting messages to everyone (will be setting up rooms later on) and everything (but this) is working great. When an end user visits any page, all currently connected users receive a message "Hi everyone!", and the user who just connected obviously sends them self the message too. All as expected so far...
The issue:
I have a page that has a button on it...
<button id="register" type="button" class="btn btn-warning">Register</button>
When clicked, this should emit a message saying 'I want to register!' (currently to everyone but that doesn't matter yet). In response, the server should listen for this and respond by emitting a message back saying 'Hmmm, will think about it!'.
'registering' is never heard at the server, and so cannot emit the reply of 'registration-response'.
Can anyone see what I'm doing wrong?
I've seen this SocketIO, can't send emit data from client and a couple others that are similar but I am already doing what they have suggested :/
NB: The app is running on http://localhost:3000/ and the io using http://localhost:8678/events. If you need any further info just let me know
Client-side JS/jQuery (app.js)
var app = app || {};
app = (function($){
$(function () {
/////////////////////////////////////////////////////
// Connect to io and setup listeners
/////////////////////////////////////////////////////
var socket = io.connect('http://localhost:8678/events');
socket.on('connected', function (data) {
console.log(data); // Always see this in the console
});
socket.on('registration-response', function (data) {
console.log(data); // NOT seen in console
});
/////////////////////////////////////////////////////
// Setup click events
/////////////////////////////////////////////////////
$('#register').on('click', function(){
console.log('click'); // Always see this, so no binding issue
socket.emit('registering', 'I want to register!');
});
});
})(jQuery);
Server-side JS
var app = require('express');
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server); //pass a http.Server instance
server.listen(8678); //listen on port 8678
////////////////////////////////////////
// Register event listeners
////////////////////////////////////////
var events = io.of('/events');
events.on('connection', function(socket){ // This is heard and callback fires
events.emit('connected', 'Hi everyone!'); // This gets sent fine
});
events.on('registering', function(data){
events.emit('registration-response', 'Hmmm, will think about it!');
});
Your socket on the server isn't set up to listen for the event.
You need to do it like this
events.on('connection', function(socket){ // This is heard and callback fires
events.emit('connected', 'Hi everyone!'); // This gets sent fine
socket.on('registering', function(data){
events.emit('registration-response', 'Hmmm, will think about it!');
});
});
The socket now knows what to do when it receives the 'registering' event and will send the response to the '/events' namespace.

How to emit an event in response to an event using socket.io?

I am new to socket.io, and trying to get it to work. I don't know what I am doing wrong here, as it seems super straightforward - yet it is not working. I suppose I am missing something obvious. Hopefully someone else can see what that is.
I am setting up socket.io to work with a node/express server. Here is a simplified version of the test I am trying to do.
Server:
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app);
var io = require('socket.io')(server);
/* socket.io test */
io.on('connection', function(socket){
socket.on('helloServer', function(clientMessage){
console.log("Server got 'helloServer' event");
socket.emit('helloClient', { message : "Hi there. We got your message: " + clientMessage.message});
});
});
The client has a function callServer that is called when a user clicks a button in the UI:
var socket = io.connect('http://localhost');
function callServer() {
socket.emit('helloServer', { message : "Hello server!" });
}
socket.on('helloClient', function (serverMessage) {
console.log(serverMessage.message);
});
When I run this code, and click the button that calls callServer, the server does get the event, helloServer, because I see that the console logs the message as expected, but the client never receives a helloClient event. It is as if the socket.emit call within the socket.on response function never gets called.
What am I doing wrong?
It appears to be ok. But, just in case, check this answer with all ways of sending data to clients and try use "io.emit" (to send to all clients). Or try sending a string instead of a json object.
I have tried this example here and it is working, just copied and pasted.

Socket.IO: Reconnect Causes Server Connect Code to Run Twice

Whenever I disconnect using socket.disconnect(); and then reconnect using socket.connect();, the server runs my handshake code twice. The strange thing is, even though the server connection code runs twice, there is only one connection in my array after reconnecting. This happens on an accidental disconnection, intentional, or even if the server restarts. Bit of code:
io.on('connection', OnConnect);
function OnConnect(socket) {
var connection = { socket: socket, realIp: ip, token: GenerateConnToken() };
connections.push(connection);
console.log('Connected');
// Client will respond to this by emitting "client-send-info".
// This is emitted once on initial connect, but twice on reconnect.
socket.emit('acknowledge', connection.token);
socket.on('client-send-info', function() {
console.log('Client Sent Info');
});
socket.on('disconnect', function() {
console.log('Disconnected');
});
}
The above code, when a client connects, disconnects, and then reconnects once, will produce the following log:
Connected
Client Sent Info
Disconnected
Connected
Client Sent Info
Client Sent Info
Why is it that, when reconnecting, the connection code will run twice, but only create one connection object?
EDIT: Upon further inspection, it seems that a different piece of my connection code is being performed twice when the client reconnects. The above code is updated to reflect the relevant information.
Strangely, the solution is completely client side. Instead of the following code:
var socket = io.connect();
socket.on('connect' function() {
socket.on('acknowledge', function() {
});
});
You have to use:
var socket = io.connect();
socket.on('connect' function() {
});
socket.on('acknowledge', function() {
});
Otherwise, the server will appear to be sending multiple emits when it is in reality only sending one, and it's the client that falsely receives multiples. With the second code format, the client successfully connects initially, disconnects, and reconnects without receiving multiple emits.
Simply, don't put any additional socket.on('x') calls inside the on('connection') call. Leave them all outside it.

Is there a way for client to send server data on socket disconnection?

Is it possible for client to send a socket data when it gets
disconnected (user closes the browser, or tab)?
Because, I found that default bind on disconnect doesn't take any input data.
//on server side
socket.on('disconnect',function(){
//in other binds, it takes 'data' as an input but this does not
});
I tried to resolve this problem by using the jQuery's unload method
like below
//on client side
$(window).unload(function(){
socket.emit('depart','I am leaving');
});
However, it does not seem to emit at all on unload. (maybe socket gets out of scope on unload?)
Is there a way to send data through websocket to the server when client disconnects?
Secondly, Is there any way that I can store a string data in socket? For instance,
socket.userName = userNameVar;
--update--
Here is how I set up environment on the serverside
io.sockets.on('connection',function(socket){
socket.on('depart',function(data){
console.log(data);
console.log("user left");
});
socket.on('disconnect',function(){
console.log("user disconnected");
});
});
and following code is in the client side.
var socket = io.connect(hostVar);
$(window).unload(function(){
socket.emit('depart','I am leaving');
});
The reason you cannot send data on disconnect is because you are disconnected. What you are asking is somewhat akin to saying "Can i still talk to the person on the phone after they've hung up on me?"
If you want to emit the 'depart' event, then you still have to capture it inside your 'connect' handler on server side:
As in:
io.socket.on('connection', function(socket) {
socket.on('depart', function(msg) {
// you should get depart message here
});
})
Your depart event will come BEFORE the connection is terminated. disconnect is only raised by server upon a successful disconnection and therefore it cannot receive any messages.
Give it a try and tell me if this works :)
Use this instead
$(window).on('beforeunload',()=>{
socket.emit('page_unload');
});
and on server side
io.socket.on('connection', function(socket) {
socket.on('page_unload', function(msg) {
// client has reloaded page or closed page
});
})

Categories