Socket IO makes multiple connections when the page is refreshed - Node JS - 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.

Related

Can't receive data from io.emit()

I am trying to send data to all clients just to test how socket.io works.
I can't seem to get any data back from the server, no matter how I try.
The event is fired, so the data gets to the server side, but it doesn't arrive to the clients.
On the server side, I do this:
io.on('connection', (socket) => {
socket.on('chatMessage', data => {
console.log(data);
io.emit(data);
});
});
The console.log() here works, so its fine until that line.
On the client side I tried to simplify things to see the result like this:
const socket = io.connect('http://localhost:5000');
socket.on('connect', () => {
socket.emit('chatMessage', {a:"fsdfsdfsd"});
});
socket.on('chatMessage', data =>{
console.log(data);
});
The socket.emit() fires, but it doesn't arrive anywhere.
I have never used socket.io before, but I read the docs and it said io.emit() sends the data to all connected clients.
Just in case, I tried with multiple clients connected, but it still doesn't work.
First thing I would recommend is to check if the client is really connecting to the server socket by adding a console.log() inside your on connection block in the server side.
Also, your io.emit(data); in the server side won't work since the first parameter of the emit function should be the event name.

How to make sure only one socket.io connection is open per user?

I'm using socket.io and socket.io-client on the Express and React sides, respectively.
On the server side, I console.log in the connection event with the socket.id, and it always displays two connections when I only have one page open, like so:
A user connected woF_Gu_8ElqMB7a5AAAC
A user connected lBAycJ6j0X5Q469SAAAD
However, when emitting messages from the front end, only one connection is used.
Here's how I set up socket.io server side:
// ** bin/www file **
var server = http.createServer(app);
const io = require('socket.io')(server);
// Get socket module and pass it the io socket from here
require('../sockets')(io);
// ** sockets.js **
module.exports = io => {
io.on('connection', (socket) => {
console.log("A user connected", socket.id); // Fires twice with different IDs
socket.on("Setup", data => {
console.log("Data received:", data); // Only fires once per emit from frontend
}
socket.on("disconnect", () => {
console.log("User disconnected");
}
}
Here's how I set up client side, though I'm not sure this matters since it's happening consistently even when I don't have this code in:
import io from 'socket.io-client';
const socket = io(window.location.origin);
Any idea why I'm getting two connections all the time? Thanks!
EDIT: Adding network screenshot.
I solved my problem and wanted to share the solution here though I don't know exactly why what I was doing previously wasn't working.
I was using React Router in App.js, and I was importing socket.io-client in a component that got routed to. That was giving a double-connection for some reason (or more, depending on where I put the const socket = io(); line).
My solution was to import socket.io-client in App.js and pass io to the component as a prop where needed, like so:
import * as io from 'socket.io-client';
const socket = io();
class App extends Component {
render() {
return (
<Router>
<Header/>
<Switch>
<Route exact path="/" render={props => (<Home/>)}/>
<Route exact path="/story" render={props => (<Start socket={socket} />)}/>
</Switch>
</Router>
);
}
}
export default App;
This defines the socket at a high level and passes down where needed, so nothing is getting called twice and I stay at one connection.
OK, let's analyze your network trace in the screenshot. I'll start at the line that says "localhost" because that is presumably where you reloaded a page.
localhost - Normal reload of a cached page
8 script files requested - All load normally
Two socket.io requests arrive that are ?EIO=3&transport=polling&t=N6pOEHc. These are not normal requests. They are missing an sid=xxxxx value from the URL.
A socket.io request arrives that is ?EIO=3&transport=polling&t=N6pOEKbsid=zhaGN0gOV6Qh3bg-AAAq. These look a normal socket.io connection initiation with a few polling requests before it switches over to a webSocket.
A fetch Ajax request for incomplete arrives.
A second socket.io polling request on the sid=zhaGN0gOV6Qh3bg-AAAq arrives. This again looks normal.
A new socket.io request arrives from ?EIO=3transport=polling&t=N6pOEPQ&sid=wWH-VzFditNgmdWNAAAr. This is the second normal looking socket.io connection request. But, we don't know why there is a second attempt to connect.
A webSocket connection sent out to socketjs-node and accepted (101 status) as a webSocket connection.
Another socket.io polling request sent by sid=zhaGN0gOV6Qh3bg-AAAq. This is probably a request to convert to a webSocket connection, but is still marked as "pending" so it apparently did not succeed (as of the screenshot, perhaps never).
Another polling request on the second socket.io connection sid=wWH-VzFditNgmdWNAAAr
manifest.json and favicon.ico are requests
4 more polling requests from the second connection &sid=wWH-VzFditNgmdWNAAAr.
2 more polling requests from the first connection sid=zhaGN0gOV6Qh3bg-AAAq which definitely indicates that the previous attempt to turn this into a webSocket apparently did not work.
So, there are actually three socket.io attempts here. The first one looks a bit mal-formed, not sure why that is. The second two look like they are both initiated by client code. Neither one of them succeeds in switching to the webSocket transport.
My best guess would be that you have mismatched socket.io versions in client and server and thus they are having a hard time making the right type of lasting connection. It could also be that there's some sort of infrastructure in the way like a proxy that is preventing a webSocket connection from succeeding.
For other possible reasons, see this: Whats the problem with the socketio connection?
Another thing you can do for debugging purposes is to change the client code from this:
io(window.location.origin);
to this:
io(window.location.origin, {transports: ['websocket']});
This will force this connection attempt to ONLY connect with a webSocket. If we see a network trace from this, we can more clearly see whether a webSocket connection succeeds of fails.
It is also unusual to be using window.location.origin as the URL. If you just leave the URL out entirely, socket.io will just connect back to the host of the page which is generally what you want.
Use Socket.once("connected") View the doc https://socket.io/docs/v4/listening-to-events/

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 fires connect event just after the second connect

I'm using socket.io with the latest version of node.js and socket.io shows an curious behavior:
The connect event fires on client side but not on server side for the first time.
After a reload or simply loading the page again the event got fired on both - client and server - side correctly.
What's wrong (with my code?)?
// Client
var socket = io.connect(window.location.protocol + '//' + window.location.hostname, {
'sync disconnect on unload': true
});
socket.on('connect', function() {
alert("Connect");
// Do other stuff
});
-
// Server
io.sockets.on('connection', function(socket) {
console.log("connection");
io.sockets.on('connect', function(socket) {
console.log("connect");
});
});
Started the server and loaded the page:
Client fires the alert, server just logs connection. Now loading the page again, it logs both connection and connect.
Update:
It seems that just the very first connection has such issues, afterwards it works everywhere as expected. Just after every node server (re)start, that behavior appears.
Note: node itself delivers the page where the socket.io is used and that works even on the first request, so a node issue should be excluded then.
Browser is also doesn't matter, it's the same on every browser.
For Socket.IO, connection is the server-side equivalent of connect on the client side. Therefore, when you're inside the callback for the connection event, the socket has already established a connection and you don't need to listen on some other event. I'm not sure what connect on the server side is, but it is not documented and does not work.
// on the server
io.sockets.on('connection', function(socket) {
// this connection has already been established
// no other handler is required
});
// on the client
var socket = io.connect();
socket.on('connect', function() {
// the connection has been established
});

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

Resources