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

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

Related

socket.io - .on not working on client side

I have some very basic code that uses socket.io
Client
var socket = io();
// Do some stuff...
socket.emit('hello', 'please like me');
// Wait for a response
socket.on('hello back!', function(msg) {
console.log('Yay, he replied:', msg);
});
Server
var app = require('express');
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.on('connection', function(socket) {
console.log('a user connected');
socket.on('disconnect', function() {
console.log('user disconnected');
});
socket.on('hello', function() {
// Code to decide wether or not I like the client
// ...
// I do like the client!
socket.emit('hello back!', 'how are you');
console.log('I said hello back!');
});
});
Hopefully you managed to get the picture. So ideally, this would happen:
Client connects
After a while, client emits hello
Server sees this, emits hello back!
Client notices the hello back! event
Everyone is happy!
But this isn't the case for me unfortunately. Instead, steps 1-3 work perfectly. But when you reach step 4 and 5, things start to fall apart. Client never logs anything after hello back! event is emitted.
This is not my full code, I figured it would make it easier for you to understand it. It's very possible that I've made some silly mistake somewhere, maybe without including it in this code. But please let me know if there is anything fundamentally wrong with what I am doing.
Cheers
This is a few years old, but in case anyone stumbles across this in the future:
My problem had nothing to do with my code shown above. Instead, it was a configuration error.
I was hosting my project on glitch.com who state that they support websockets, but the error was caused because the server was not able to get across to the client (client never received any data from server at all after websocket connection was opened).
This was an error that I had in 2018 with glitch.com, and I know that other people have had it too. It also seemed to be related somehow to websockets connecting via a domain name and with SSL, but I can't recall the exact circumstances.

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!

socket.io client connection cannot be made on the 2nd time

Currently, I am implementing an API using nodejs express, then it needs to connect to socket.io and send event.
The API is located in socket.io-client (client), and it connects to socket.io (server)
1st API call: success
The connection is made for the 1st call of the API, message is sent and socket can be disconnected, with the 'disconnect' callback is invoked both on client and server side.
2nd API call: failure
When the API is invoked the 2nd time, the connection to server cannot be made, 'client' callback on client side is not called.
3rd API call: success
Then I tried to restart the client side, keeping other things unchanged. The API is called again, and the connection to socket.io is made successfully and everything is fine.
Can anyone explain the logistics behind this?
Updated
client.js
App.getByUserId(message.to_id, function(error, app) {
var socket = io.connect('http://127.0.0.1:9002');
socket.on('connect', function(){
console.log("client connect socket id:" + socket.id);
console.log("appkey:" + app.private_token);
socket.emit('appkey.check',{appkey: app.private_token, uuid: message.to_id.uuid}, function(data){
socket.emit("forceDisconnect");
socket = null;
});
});
You just hit one of Socket.IO's many "features" or "bugs" depending how you see this. Socket.IO tries to be smart and re-use connections (which causes a lot of connection issues actually) The way around this is use the force new connection option in your io.connect:
io.connect('http://127.0.0.1:9002', { 'force new connection': true });
What you could also do is use https://github.com/primus/primus which wraps Socket.IO if you use the socket.io transformer. Internally, it completely removes the use of the io.connect and uses the much more lower level io.Socket constructor to create more stable connections that you would get with a stock socket.io.
With socket 1.0+, you have to use this for forcing new connection.
io.connect(SERVER_IP, { 'forceNew': true });

emitting data via socket on browser close /window close

I need to send data to nodejs server via socket.io when the user closes the browser tab .
I tried doing :
var data={};
window.onbeforeunload = function() {
// i have a object to be sent
data.data1='abcd';
data.data2=1234;
socket.emit("senddata",data);
}
This code works when the user navigates around clicking links on the site but doesnot work when the user closes the browser tab
I also tried configuring the socket io on server side as below .. thinking the error may be due to socket connection being closed before emitting data:
var io = require('socket.io').listen(app.listen(port));
io.configure(function () {
io.set('close timeout',12000);
});
It also didnt work most of the time.
I also tried this on client side:
var socket = require('socket.io').listen(80, {
"sync disconnect on unload":false
});
It also did not work
I had tried receiving data like this
var io = require('socket.io').listen(app.listen(port));
io.sockets.on('connection', function (socket) {
socket.on('senddata', function (data) {
// data processing
});
});
please ..help me with this problem..thanks in advance..
When user connects - register on server side the time it happened.
Socket.IO has heart beating and pinging functionality. So just subscribe to disconnect event on server side and once it happens - means client disconnected - and you have on server time when client had connection. So that way you have timespan of client session.
Do not trust client to tell you any time or important data, as client can simply 'lie' - which leads to hacks/cheats/bugs on your server-side.
There is no reliable way to send data just before disconnect from client-side at all. There is nothing in Socket.IO for that, nor in just one of transports (WebSockets). As well as there is too many different scenarios of disconnection (power off, force close, ethernet cable out, wifi lose, etc).

Socket.io and modern browsers aren't working

I'm having some weird issues with socket.io and modern browsers. Surprisingly, with IE9 works fine because fallbacks to flashsocket which appears to work better.
In my server (with express)
var io = socketio.listen(server.listen(8080));
io.configure('production', function(){
console.log("Server in production mode");
io.enable('browser client minification'); // send minified client
io.enable('browser client etag'); // apply etag caching logic based on version number
io.enable('browser client gzip'); // gzip the file
io.set('log level', 1); // reduce logging
io.set('transports', [ // enable all transports (optional if you want flashsocket)
'websocket'
, 'flashsocket'
, 'htmlfile'
, 'xhr-polling'
, 'jsonp-polling'
]);
});
On the browser I can see in the Network tab (on Chrome) that a websocket is stablished and get in 101 Switching Protocols in Pending mode. After that, appears xhr-polling and jsonp-polling (what happend to flashsocket ? )
The worst part is that info don't go back and forth. I have this on connection:
io.sockets.on('connection', function (socket) {
// If someone new comes, it will notified of the current status of the application
console.log('Someone connected');
app.sendCurrentStatus(socket.id);
io.sockets.emit('currentStatus', {'connected': true);
});
And on client:
socket.on('currentStatus', function (data){ console.log(data) });
However I only be able to see that log when I turn off the server which is launched with:
NODE_ENV=production node server.js
What am I doing wrong?
Finally, after really banging my head against a wall, I decided to test in several environments to see if it was a Firewall issue since the machine is behind several ones.
It turned out that no one but me had the problem so I checked the Antivirus (Trend Micro) and after disabling, Chrome/Firefox were able to make their magic.
Moral of the story
Besides what it says here - Socket.IO and firewall software - whenever you face an issue that nobody in the internet seems to have (ie, not logged on github nor the socket.io group) it's probably caused by your Antivirus. They are evil. Sometimes.
You should just be having the socketio listen on the app itself.
Also, I have never need to do all of the server side configuration with the socket that you are doing - socket.io should work out of the box on most browsers without doing that. I would try first without configuring.
Also, on the server, you should emit from the socket that is passed to the callback function rather than doing io.sockets.on.
var io = socketio.listen(app);
io.sockets.on('connection', function (socket) {
// If someone new comes, it will notified of the current status of the application
console.log('Someone connected');
app.sendCurrentStatus(socket.id);
socket.emit('currentStatus', {'connected': true);
});
on the client, you need to connect first:
var socket = io.connect();
socket.on('currentStatus', function (data){ console.log(data) });
If you want to see an example of two way communication using socket.io, check out my Nodio application.
The server side:
https://github.com/oveddan/Nodio/blob/master/lib/Utils.js
And the client side:
https://github.com/oveddan/Nodio/blob/master/public/javascripts/Instruments.js

Resources