emitting data via socket on browser close /window close - node.js

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

Related

socket.emit within collection.find.each problem [duplicate]

So, I am still in the experimental phase of Socket.io, but I just can't figure out why my code is doing this. So, I have the code below and when I console.log the code, it repeats the the connection even when there is only one connection. Do you know a solution?
io.on('connnection', (socket) => {
console.log("A new user is connected.")
})
Client side:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io()
</script>
Node.js Console:
A new user is connected.
A new user is connected.
A new user is connected.
A new user is connected.
A new user is connected.
A new user is connected.
A new user is connected.
...
(Note: there is only one connection, and I have already cleared the browser cashe)
Here are some of the possible reasons for socket.io connecting over and over:
Your socket.io client and server versions do not match and this causes a connection failure and an immediate retry.
You are running with some infrastructure (like a proxy or load balancer) that is not configured properly to allow lasting webSocket connections.
You are running a clustered server without sticky webSocket connections.
You have put the server-side io.on('connnection', ...) code inside some other function that is called more than once causing you to register multiple event handlers for the same event so you think you're getting multiple events, but actually you just have multiple listeners for the one occurrence of the event.
Your client code is calling its var socket = io() more than once.
Your client page is reloading (and thus restarting the connection on each reload) either because of a form post or for some other reason.
FYI, you can sometimes learn something useful by installing listeners for all the possible error-related events on both client and server connections and then logging which ones occur and any parameters that they offer. You can see all the client-related error events you can listen to and log here.
To solve repetion problem write your code like that for socket:
io.off("connnection").on('connnection', (socket) => {
console.log("A new user is connected.")
})

Socket IO makes multiple connections when the page is refreshed - Node JS

I have developed a scrapping tool, that scraps jobs from all websites and save them into the database. I have made my own default log where I get messages(errors, info) etc. I am using socket.io to update my view in real time and for database too.
The problem is when I start the app it perfectly get make socket, and database connections. But when I try to refresh the page, the same connection is made again twice with the same message and different ID's. As much I refresh the page the connections are made, and the id get changed, but for all made connection they use one ID,
Below is the Log which shows it :
I have uploaded this video, please check this as well. Try to watch the very beginning, and then at 01:41 and 03:06, before starting scrapping of the first site the connection is established, but when second website scrapping is started, the Internet Connection message is given twice, and the same stands for when third website scrapping is started, the number of messages get doubled every time. I don't know why.
I have tried following the answer of this question, but still no success. The code is 600+ lines on server file, and 150+ lines second file and same on the client side, that's why I can't upload all and it's a bit confidential.
But the socket connection on the client and server is like this:
Server Side
const express = require("express");
const app = express();
const scrap = require("./algorithm");
const event = scrap.defEvent;//imported from another file
const ms_connect = scrap.ms_connect;
const server = app.listen(8000, function(){ console.log('Listening on 8000'); });
const io = require("socket.io").listen(server);
const internetAvailable = require("internet-available");
app.use(express.static(__dirname + "/"));
app.get("/scrap",function(req,res){
res.sendFile(__dirname+"/index.html");//Set the Default Route
io.on("connection",function(socket){ //On Socket Connection
socketSameMess("Socket",'Sockets Connection Made on ID : <span style="color:#03a9f4;">'+socket.id+'<span>');
ms_connect.connect(function(err){//On Connection with Database
if(err) socketSameMess("database_error",err+" "); // If any error in database connection
socketSameMess("Database ",'Connected to MYSQL Database Successfully...');
})
})
})
function eventSameMess(auth,mess){
//hits the custom console
defEvent.emit("hitConsole",{a:auth,m:mess});
}
Client Side
var socket = io.connect('http://localhost:8000');
socket.on('connect',function(){
if(socket.connected){
initDocument();
}
})
Getting multiple messages
Here are some thumb rules for socketio
if you listen to any event once, you'll get the message once in the callback
if you listen to any event twice, you'll get the message twice in the callback
if you listen to any event nth time, you'll get the message nth in the callback
If you're listening to any event on page load, don't forget to listen off that event before you leave the page (if an event is not globally)
If you forgot to listen off and if you again re-visit page. you'll start listening to events multiple times. because on page load you're listening to the event. and the previous event is not yet stopped by listen off
Don't listen to any event in loop, It may listen to it multiple time and you'll get multiple messages on a single change.
connect socket
const socket = io('http://localhost', {
transports: ['websocket'],
upgrade: false
});
listen and listen off an event
let onMessage = (data) => {
console.log(data);
}
//listen message
socket.on('message', onMessage);
//stop listening message
socket.off('message', onMessage);
remove all listeners on disconnect
socket.on('disconnect', () => {
socket.removeAllListeners();
});
Use Firecamp to test/debug SocketIO events visually.
i was having the problem that each client was getting two socket connections. I thought something is wrong with sockets.
but the problem was
FrontEnd -> React
Created the template using create-react-app
In index.js file it uses something called React.StrictMode
This mode renders some of the App.js components two times.
Just remove that React.StrictMode and try to see if your problem is solved.

How many times can Socket.io 'connection' and 'disconnection' events be fired for single client?

EDIT: I see that I'm getting ping timeout and transport error reasons in my handler for disconnect on the server. This makes it difficult to maintain state in my server (I'm trying to keep track of which users are connected in a chat-like setup(. I was reading that it may be related to background tabs in Chrome (which I'm running). Does anyone have any experience with these 'spurious' disconnect events?
I'm new to Socket.io and am having some trouble understanding the connection and disconnection process.
As I understand it, the server receives the connection event once when a client connects, and one registers all the handlers for that client in the callback on on.('connection'). Is that true?
I want to maintain an of connected users, so I add a user to that array on the connection handler.
Should I then listen for the disconnect event to know when to remove a user from that array? Can I be guaranteed that that event will only be fired once?
It's a bit confusing, because on the client side, there is the connect event, which apparently can be fired multiple times -- the documentation says
// note: you should register event handlers outside of connect,
// so they are not registered again on reconnection
which is a different paradigm than on the server side, where all the handlers are registered inside the connection handler. But if the client-side connect event can fire on re-connection, what is the reconnect event for? (The docs says this event is "Fired upon a successful reconnection.")
In general I'm confused about the process of connection, disconnection and re-connection and how this relates to events, whether it happens "randomly" due to connection issues or only under the programmer's control, and how many times one should anticipate receiving each of these events -- once only for server, multiple times for client?
Thanks for any help!
I'm new to Socket.io and am having some trouble understanding the
connection and disconnection process.
Welcome to the wonderful world of Node.js + Socket.io It's super powerful!
As I understand it, the server receives the connection event once when
a client connects, and one registers all the handlers for that client
in the callback on on.('connection'). Is that true?
Correct. Take a look at this example of my code:
Server-side
var clients = []; /* stores all sockets on the fly */
io.on('connection', function (socket) {
clients[socket.id] = socket; /* keeps an array of sockets currently connected */
socket.on('disconnect', function (data) {
console.log(socket.id + " disconnected");
delete clients[socket.id];
});
});
Client-side
socket = io.connect(YOUR_SOCKET_URI, { transports: ['websocket'] } );
socket_delegates();
socket_delegates = function() {
// Socket events
socket.on('connect', function(data) {
/* handle on connect events */
});
socket.on('disconnect', function () {
/* handle disconnect events - possibly reconnect? */
});
socket.on('reconnect', function () {
/* handle reconnect events */
});
socket.on('reconnect_error', function () {
/* handle reconnect error events - possible retry? */
});
}
Should I then listen for the disconnect event to know when to remove a
user from that array? Can I be guaranteed that that event will only be
fired once?
Yes. You will see in the above server code that we listen for disconnect and then do what we need to.
Nothing should be random. You should have code in place to handle the connect, disconnect on the server side and code to handle the connect, disconnect and reconnect on the client side.

Attaching event emitter to socket.connected

I am currently writing an Electron app, for which in the main process I want to talk to a server over websockets.
Part of my main process' code base depends on the user's socket connection status. I require the socket.io-client library
const socket = require('socket.io-client')(host);
which gives me access to the variable socket.connected, which is true or false according to whether a connection is established to the server.
Thus, what I would like is to attach an event emitter to this variable. I have made it to work with polling
var events = require('events').EventEmitter;
var event = new events();
// Emits successfully every 200ms 'Connection: true|false'
event.on('status', function(status){
console.log('Connection: ', status);
});
setInterval(function() {
let status = socket.connected;
event.emit('status', status);
}, 200);
but was wondering whether this truly is the way to implement it. To me it seems strange to have to resort to polling in an async framework like nodejs. On the other, I could not find other ways to implement. Best-case scenario would be to attach somehow an event emitter directly to socket.connected, but was unable to find how to do that. Could anybody advise me on a better way to implement?
Thanks
You can get notified of the completion of a client connection with the connect event:
socket.on('connect', function() {
// client socket is now connected to the server
});
socket.on('disconnect', function() {
// client socket is now disconnected from the server
});
Documentation for client events here: http://socket.io/docs/client-api/#manager(url:string,-opts:object). There are other events in that doc if you also want to see other things like a reconnect.

Socket.io doesn't send disconnect event to NodeJS in IE8/9

I use NodeJS with socket.io for my chat application. When client refreshes/closes the window or navigates to different URL I need client to emit "disconnect" event to NodeJS server. All works nice with excpetion of IE8/9. When refresh happens "disconnect" event is not send to server so server is not aware that this particular client is no longer connected.
I managed to use:
window.onbeforeunload = function(e) {
socket.disconnect();
};
and this takes care of clicking back/forward button and then the server is informed about client disconnecting. Refreshing the page or closing the tab however doesn't send disconnect to server. It seems that refreshing the page is too quick so the socket.disconnect() has no chance of executing. It seems so as if I do alert like below, client pauses for alert window and server receives disconnect message.
window.onbeforeunload = function(e) {
socket.disconnect();
alert("hey watchout!");
};
Now, is there any way to make IE8/9 send disconnect event to NodeJS when page is refreshed?
You can send information back and forth and find the time of the last reply, compare it to now and if the difference is greater than a number, disconnect the client, then reconnect when the client starts sending again.
You can use something like:
On client:
socket.on('ping',function(){socket.emit('pong',(new Date()).getTime());});
On server:
socketReferences = new Array();
io.on('connection',function(socket){
socketReferences.push(socket);
socket.on('pong',function(data){
if(new Date()).getTime()>5000){
// disconnect code here
}
});
});
setInterval(function(){
for(socket in socketReferences)
socketReferences[socket].emit('ping','');
},700);

Resources