Double connection in Socket.io - node.js

My question is very simple. I have a Node.js server with the following code
io.on('connection', function (socket) {
console.log('connection');
});
My web page contains just
var socket = io();
I open the app in one window. Then I open it in another. The console shows three connections. If I refresh one of the windows, the console shows a total of six connections. I refresh once more, I get 10 connections. Once more, 15 connections.
How is that possible? I would like one connection per page load, how can I achieve that.
Thanks for your attention!
NB: I don't know if it is important, but I am also using Express, Mysql and sessions

I had to put the io.on() outside my app.get().

i had same problem instead of io.on('connection')
just use
io.once('connect')
EDIT: here is code
io.once('connect', function (socket) {
console.log('connection');
});

Related

long-running applications and socket.io

I have a web application that accepts an input from the client (browser) and calls an application at the server side with the input. The problem is that the application will run for a long time (about 20s). In order to not block the client (browser) and show the progress to the user, my server side POST function returns immediately and feeds the user
input to the application. Once the application computed the result, I send the result to the client using socket.io. Another twist to the scenario is that the application can not be repeatedly launched and closed (will cause some problem with CUDA) so the whole server side runs just one instance of the application. A sketch of my server-side code looks like the following. Embedded in the code are the three questions that I have searched through the Internet and tried various solutions but could not work out. Any help on them is really appreciated. If this is not the right place to ask, I would be thankful to any feedback about where to ask this question.
var express = require('express');
const{ spawn }= require('child_process');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var darknet = spawn('./darknet', other arguments...) ;
io.on('connection', function(socket){
app.socket = socket;
console.log('A connection has been established');
})
darknet.stdout.on('data',(data) =>{
// This function is called once darknet finished computation and wrote the result to the stdout
// Question 1: now need to send the data back to the client but have no access to any socket here?
})
io.on('connection', function(socket){
//Question 2: how to store this socket so that I can use it in a solution to the Question 1? Can I use session? */
//Question 3: I observed that once the client side refreshed its page (for example, uploaded an image), the previous socket will be closed and a new socket will be established. How do I make sure that I send the output from the application to the right socket since the original one may be invalid when the output is ready to be sent?
})
app.post('/predict', function (req,res){
darknet.stdin.write(user_input+'\n');
res.render();
})

Express specific socket.io connections per page

So currently my setup is I have a standard app.get('/', etc for my index and inside here, I have my io.on('connection', function etc). Now the goal is so that every time someone connects to only the homepage i can get that socket with io.on(connection and send things to it that way, and my syntax and all is fine however i believe having my io.on('connection' inside a route is my issue.
The problem: Whenever someone connects to my website after i start the server, it works great, for debug examples i have a console.log inside of it and its called once and we are good. However if that same person reloads the page my io.on('connection' is called again, and this time iw ill get 2 console.log's... when I again reload I then get 3 and so on and so on, no matter if i close the page and reopen it or come from a different ip. It seems as if the connection isnt closed when I reload and all the still hanging connections are recalled when I reload.
I know this is a little unorthodox with me not posting my code. Its not the syntax, here is an example of essentially the set up described. Oh and also i need access to the req input from the app.get which is why its in there in the first place, I have passport variables saved in it.
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
io.on('connection', function(socket){
console.log("1 connection");
});
});
I hope this explains my issue well enough. When i looked for answers first i found a bunch of stuff about routing, but was confused. Any help is appreciated!
For what I got from the question and the comments.
You are doing it wrong way. You should never put the ONs and EMITs of socket connection where they are called multiple times as they are appended every time.
for example : first time this is called
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
io.on('connection', function(socket){
console.log("1 connection");
});
});
the io.ons['connection'] has the value
function(socket){
console.log("1 connection");
}
second time you call it the callback is appended again. and the value of io.ons['connection'] is now
function(socket){
console.log("1 connection");
}
function(socket){
console.log("1 connection");
}
So it prints console.log two times
SECOND :
if you want to do the further work after the user is logged in.then you need to verify the user here, you can use a socket.emit('init',..... from client side
and server-side socket.on('init',...... will verify the user and can access else return and close the connection.
Never, ever put event handlers like io.on() inside app.get() handlers. That is just wrong and will not do even close to what you want. It will not have an event handler in place until someone hits your page and then every time someone hits that page, it will add a duplicate event handler. Both of these are wrong.
The structure should look like this:
// watch for people hitting the / route in the browser
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
// listen for incoming webSocket connections
io.on('connection', function(socket){
console.log("new connection");
});
This will prevent the duplicate event handlers you were getting.
In case what you were trying to do is to listen for incoming socket.io connections only from a specific page, that is not a support capability. Socket.io connections are from a browser, not from a specific route. You can get access to the cookies associated with the hosting page and the code in the web page making the browser can connect to something like a specific namespace, but there is no built in correlation between an incoming socket.io connection and a specific route the way there is with http requests.
If you're trying to get access to a session object from an incoming socket.io connection, that can usually be done via the cookies associated with the start of the socket.io connection.

Socket.IO: connection to a non-existing namespace

First post, i'll try to be as clear as possible :)
I'm trying to create on Demand namespaces on my SocketIO/NodeJS App.
Basically, the server create a specific namespace for each client.
I need to handle, server side, the case where the client try accessing a non-existing namespace.
The idea is to avoid any unwanted connection server-side, or at least, handle it to force the disconnection.
But while testing, it seems that when i try this, on client Side :
var socket = io("thisNameSpaceDontExist");
socket.on('connect', function(){
window.console.log('connected to server');
})
The 'connect' event won't trigger, which seems perfect !
Doing a console.log on socket, it displays this:
connected: false
disconnected: true
But the main problem, is that, Server Side, it's different, there is an active connection...
While doing some research, i found this issue https://github.com/Automattic/socket.io/issues/1867, still, i'm on the last version at this time: 1.3.5
for information, the socketIOHandler code i'm using:
io.on('connection', function (socket) {
console.log("[SocketIOHandler::Connection] +1");
socket.on('disconnect', function () {
console.log("[SocketIOHandler::Disconnection] -1");
});
});
PS:
Also find some issues and MR claiming the support of dynamic namespaces: https://github.com/Automattic/socket.io/issues/1854, but these are not merged, so i don't really understand the behavior on my code...
Thank you!

Node.js server.close() won't close due to active connection

I'm trying to show some information before the application is closed. So, I create an event that will be fired when the server receive a SIGINT. This code will work if no connection is ever made. However, if there had been a connection localhost:4040, the server will never close as the server think there is still an active connection(connection count will be 1). The part I don't understand is why Node.js still think there is an active connection when the request has already finish. Is there any ways to kill a connection or my current way of closing the request is wrong?
Here is the code of What I'm trying to accomplish:
var http = require('http')
var server = http.createServer(function(req, res){
res.end('test');
}).listen(4040);
process.on( 'SIGINT', function(){
server.getConnections(function(err, count){
console.log('connection:' + count);
})
server.close(function(){
process.exit();
});
})
Some ideas I have:
saving a copy of the sockets I receive and close them individually
Hope someone can give me some advice in solving this.Thanks
store all sockets from you have and close them manually
use process.exit() and destroy the entire process instead
use domains and do a scary deprecated domain.dispose()

socket.io - works first time, not second time onwards

When I start my node.js server and client gets connected, I am able to send a request from client (socket.emit) and get a response (socket.on('rentsAround'....)). But when I connect 2nd time onwards, the client is able to send, but server can not send or emit. So I have to restart the server again. I understand that it is working as expected, but somehow my understanding is wrong somewhere... Would someone please point out.
client side:
========
var socket = new io.Socket();
socket = io.connect();
socket.on('rentsAround', function(data){
registration.handleRentsAround(data);
});
socket.on('locationDetailsRes', function(data){
registration.handleRentsAround(data);
});
socket.on('connect', function(data){
alert('inside connect on client side');
});
socket.on('disconnect', function(){
// do something, if you want to.
});
.............
socket.emit("searchRent", {"lat":lat, "lng":lng});
server side:
========
socket.sockets.on('connection', function(client){
client.on('searchRent', function(msg){
console.log('inside on connection');
// do something and reply back
client.emit('rentsAround',{"totalRents":docs.length, "rents":docs});
});
client.on('disconnect', function(){
sys.puts("client disconnect");
mongoose.disconnect();
});
Socket.io 0.7 onwards will try and reuse connections to the same host. In my experience I've found this behaviour can be a little flakey.
I can't tell from the small code sample you provided, but I suspect the problem is that the second call to connect() is trying to reuse the first (closed) connection.
The workaround is to pass the 'force new connection' option when you call connect(). Eg:
io.connect("http://localhost", {'force new connection': true});
Your second line discards the object created in the first line. Simply doing this should work:
var socket = io.connect();
The problem with first send and second fail could be due to browser/protocol. I have seen such behaviour with Internet Explorer and XHR transport, and also with Opera using JSONP.
If you are using IE, try switching to JSONP and it should work properly. This can be done on the server side, by supplying the transport list to configuration. Just make sure JSONP comes before XHR. Something like this:
sio.set('transports', [
'websocket'
, 'flashsocket'
, 'jsonp-polling'
, 'xhr-polling'
, 'htmlfile'
]);
As of socket.io 1.0, two settings control this behaviour:
"force new connection":true, on the client connect() call.
"cookie":false, on the server Server() constructor.
Apparently, both produce the exact same behaviour.
The second method is, as of today, undocumented. However, looking at the source code you can see that all options passed to socket.io Server() are passed to the internal Engine.io library Server() constructor, which lets you change any of the options there. These options are documented here:
https://github.com/LearnBoost/engine.io

Resources