Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple sockets open after reconnect #430

Closed
theyak opened this issue Jul 28, 2011 · 59 comments
Closed

Multiple sockets open after reconnect #430

theyak opened this issue Jul 28, 2011 · 59 comments
Labels
bug Something isn't working

Comments

@theyak
Copy link

theyak commented Jul 28, 2011

I've noticed this both on my socket.io application and someone else's. When a reconnect occurs, it's common for more than one socket within a client to be open, which should never happen.

Here's a log I got from my own test application when I had a disconnect/reconnect.

*** Disconnect
*** Reconnecting with delay 1000 Attempts: 1
*** Reconnecting with delay 2000 Attempts: 2
*** Connecting with xhr-polling
*** Connecting with xhr-polling
*** Reconnect with transport type xhr-polling Attempts: 2
*** Connected
*** Connected

When this happens, I get duplicate messages sent, one for each connected socket, even though there should only be one. It is confirmed by Firebug that there are, in fact, two sockets from the client connected. My best guess is that this is in the client code, perhaps not closing the first reconnection attempt.

Of course, the real question might be why was there a disconnect in the first place?

@3rd-Eden
Copy link
Contributor

The disconnect is fired because technically, the client has disconnected from the server. And is disconnected until the reconnect event is fired again.

But the rest is a bug.

@ghost ghost assigned 3rd-Eden Jul 30, 2011
@n3m6
Copy link

n3m6 commented Jul 31, 2011

I think this is the reason for a bug in my application as well -

On the server side, I've created a tailable cursor on mongodb to fire every time there's a new insert. This message is then sent via io.sockets.emit() to everyone connected.

But instead of receiving just one message per event, I get multiple repeat messages on the client side.

I'm on an extremely unreliable internet connection, so my guess is that this bug is affecting my code as well.

@mfkp
Copy link

mfkp commented Aug 8, 2011

Were you guys using expressjs? I had this problem with express, rewrote it without and it worked fine.

@tj
Copy link
Contributor

tj commented Aug 8, 2011

Express would have absolutely nothing to do with this @mfkp, must have been doing something weird

@3rd-Eden
Copy link
Contributor

3rd-Eden commented Aug 8, 2011

Agreed with @visionmedia, its a bug in socket.io not with Express. Because the current reconnect implementation was still designed for 0.6, so it's missing some checks and clean ups.

@mfkp
Copy link

mfkp commented Aug 8, 2011

Ah, I see. Nevermind, carry on ;-)

@nodenstuff
Copy link

+1 to this. Intermittent issue in our chat app where socket.io opens multiple connections. The client then receives dupes of all emits.

@ghost
Copy link

ghost commented Nov 10, 2011

+1. Websockets & chrome. Laptop goes to sleep -> app reconnects after wakup -> double events. Happens only when connecting to remote server. Cant reproduce this locally, must be some reconnect/network latency problem.

@vedratna
Copy link

is there any workaround to get rid of multiple connection after this?, e.g from client side, if I do socket.disconnect(), will it disconnects all the connections? As I want to avoid multiple updates. does following work?
socket = io.connect(url)
socket.on('connect', function(){
if(multipleConnect) {
socket.disconnect();
socket.removeAllListeners('connect');
io.sockets = {};
socket = io.connect(url);
socket.on('connect', functionToConnect);
}
})

@cris
Copy link

cris commented Nov 22, 2011

Please, read this #474 (comment) .
It explains why this bug occurs and how it can be reproduced.

@CameronJ
Copy link

@3rd-Eden - Any idea where this fix falls on your todo list / priorities? I've got an app that I'm building and I was planning on using this for it, and would love to be able to tell my client that it will reconnect properly from iOS devices. It disconnects after the application is put in the background or device is put to sleep.

Or do you have any idea about how I can code a workaround? I've been working on a few things for the past couple days, but best case always seems to leave too many connections open and drop all of the sockets stored data. The data isn't the end of the world I can use the reconnect trigger from the client to solve that problem, but the concurrent connections is a bit ugly.

Thanks!

@davidfooks
Copy link

@cris I'm not sure that this is the same bug that you mention. I have a very simple example of the bug without a slowdown on the server.

I can clearly reproduce this issue by:

  1. Implement a simple heartbeat client that sends heartbeats on 1 second intervals.
  2. Count the number of new connections server-side.
  3. Count the number of disconnections server-side.
  4. Start the server and make a connection with a client.
  5. Break the network connection between the client and server.
  6. Wait until the server times out and emits a disconnect event.
  7. Reconnect the network connection.

Observe that when the client reconnects it creates 2-4 connections emitting a 'connect' event for each. The server receives 2-4 connections from the client and emits a 'connection' event for each. The client doesn't ever close any of the incorrectly started connections.

@davidfooks
Copy link

server.js: https://gist.github.com/1717643
client.html: https://gist.github.com/1717648

@theyak
Copy link
Author

theyak commented Feb 1, 2012

Thanks. I really do think this bug should be a priority. Many commercial companies that don't know better try to hire people to develop against the socket.io framework, thinking it works well. Granted, socket.io is free, so maybe this commercial companies should start looking at commercial products. But again, I think this really needs to be prioritized as very high priority. This bug has existed since 0.7.0 and is easily reproducible.

@cris
Copy link

cris commented Feb 3, 2012

@davidfooks, @theyak. I fixed this issue for me long time ago, and it works without a fuss.

To fix, you should:

  1. Apply this patch: Partial fix #237 in client and #474 in server for duplicated reconnection in JSONP socket.io-client#342
  2. Disable AJAX-handshake(and let handshake to be only via JSONP), as discribed in pull-request comment.

@theyak
Copy link
Author

theyak commented Apr 11, 2012

How do you disable AJAX handshake? I assume you can still use all the connection types, this will only affect handshake?

@kul
Copy link

kul commented Apr 25, 2012

+1 please fix this :)

@ycarmel
Copy link

ycarmel commented Apr 29, 2012

I had the same multiple connect on re-connect issue. I think this is a severe issue...
The cause is that the Socket.connect method is called but the conneting flag is only set to true after handshake is completed, in case one of the matbeReconnect timers (timers handling the reconnect) wake up during the handshake process, they will calll Socket.connect again causing multiple reconnects.
I have solved the issue by calling self.reconnecting at the beginning of Socket.connect method.

@ycarmel
Copy link

ycarmel commented Apr 29, 2012

Created a patch: socketio/socket.io-client#424

@sadtaco
Copy link

sadtaco commented May 15, 2012

Any chance of merging this?
This bug is making a bad bug in my app as well.

@Toktik
Copy link

Toktik commented Jul 9, 2012

This bug still exists. Tried both patches. No success.

@soulnafein
Copy link

+1 I have this problem a lot using xhr-polling I didn't try the patches yet

@KasperTidemann
Copy link

+1, I too have this problem with the duplicate reconnections.

Whenever Node.js is restarted (i.e. when running via supervisor), my client(s) reconnect X times the number of times Node.js has been restarted from the point where the client(s) connected initially. The bug causes events to be emitted once per reconnection from the client-side - this is not just a question of duplicates.

I tried socket.on('disconnect', function() { socket.disconnect(); }); on the client-side, but that does not work. :/

@KasperTidemann
Copy link

Investigating this a bit further, it seems I found what caused my problems. It's not a bug, but a wrong implementation of the client-side code from my part. facepalm This is what I originally had:

PROBLEM:

var socket = io.connect();

socket.on('connect', function () {

  console.log('User connected!');

  socket.on('message', function(message) {

    console.log(message);

  });

});

The above client-side JavaScript caused the multiple calls to console.log() when the client(s) reconnected. This is what I replaced the above with:

SOLUTION:

var socket = io.connect();

socket.on('connect', function () {

  console.log('User connected!');

});

socket.on('message', function(message) {

  console.log(message);

});

Now, multiple messages are not being sent back and forth when clients reconnect to the server. Can anybody else confirm that a change of their client-side code fixes the problem?

@xdanx
Copy link

xdanx commented Jul 25, 2012

Hi. I had the same issue. When I was restarting node ( or when the connection timed-out ) and the client reconnected , I was receiving the same message emited by the server by n time ( where n was the number of reconnects ).
I solved this by moving all my handlers from inside the socket.on('connect' function() {... }); function to outside of it.

The code above does what it takes.
This is my full answer from the mailing list:
https://groups.google.com/forum/?hl=en&fromgroups#!topic/socket_io/X9FRMjCkPco

@KasperTidemann
Copy link

@xdanx, awesome, thanks for the reply.

@xoba
Copy link

xoba commented Jul 31, 2012

yes, this seems to work for me too: putting the socket.on('message') code separate from 'connect' event code

@sadtaco
Copy link

sadtaco commented Aug 1, 2012

But what about "Connection"?
And what about the "socket" object in callback?

/edit Nevermind, I see, 'connect' is on the client. I was still getting issue with reconnect spamming when I hadn't done that. But that was in 0.9.6

@SiasMey
Copy link

SiasMey commented Sep 5, 2012

I seem to have the same problem as well... Tried the above fix of moving the message code to seperate blocks.. but noticed that I never had it together.

any news on other workarrounds for this in 0.9.8?

@KasperTidemann
Copy link

@esanai No problem, glad it worked!

@ketban
Copy link

ketban commented Apr 11, 2013

Hi, I have the same problem and I noticed that every time the connection is reconnected, a new client socket id is created. The solution is either use io.set('transports', [ 'jsonp-polling' ]); or use KasperTidemann's solution?

@samuelclay
Copy link

@KasperTidemann My goodness, man, that is exactly the answer to my problems! See this commit: samuelclay/NewsBlur@76cbbd8#L2L3887

@ZiCog
Copy link

ZiCog commented Apr 14, 2014

I can reproduce a double connection event following a connection error at will with this simple client and server code in a single node.js file:

"use strict";

var server = require('socket.io');
var client = require('socket.io-client');

setTimeout(function () {
    var io = server.listen(8888);

    io.of('/chat').on('connection', function (socket) {
        console.log('Server: /chat connection');
        socket.emit('greeting', 'Hello, who are you?');
    });

    io.sockets.on('connection', function (socket) {
        console.log('Server: connection');
    });
}, 2000);

var socketAddress = 'http://localhost:8888/chat';
var socket = client.connect(socketAddress);

socket.on('connect', function () {
    console.log("Client: connect");
});

socket.on('greeting', function (data) {
    console.log("Client: greeting: ", data);
});

socket.on('error', function () {
    console.log("Client: error");
    socket.socket.reconnect();
});

Any work a rounds or fixes in sight?

Sorry I also posted this to issue #474.

ambarket added a commit to ambarket/botbattle that referenced this issue Feb 22, 2015
Separated io.connect() from socket.on('connect', ...) and others as
suggested by
socketio/socket.io#430 (comment) 
I have a feeling this isn't the whole problem but worth a shot.

This is a relatively old thread and there are a few references to
suggested patches. Seems like this reconnect issue is something people
have been struggling with for a while... 

I have a feeling its some subtlety in our code rather than an issue with
the api.
@iguanahotsauce
Copy link

I can reproduce this error fairly consistently using an iPhone with iOS 9.3.2 and Chrome Version 50.0.2661.95 and on Safari for iOS with version 1.4.6 of Socket.IO

I am only able to reproduce this on mobile and it hangs my page on the request to socket.io.

I have a simple .on('connect', function(socket) { console.log('Connected'); }); and it logs Connected twice when the error occurs which leads me to believe it is trying to open multiple socket connections at the same time.

screenshot 2016-05-27 13 03 44

Does anyone know a workaround for this?

@raooll
Copy link

raooll commented Aug 10, 2016

Why was this issue closed ??

@ZiCog
Copy link

ZiCog commented Aug 10, 2016

My example code of Apr 14, 2014 above no longer produce double connection events. There is a connect event for '/chat' and one for the socket itself. Which seems reasonable.

There is also no error even in the client anymore.

This is with socket.io 1.4.8 and node 6.3.0.

@basickarl
Copy link

This bug is affecting me atm.

@leemlwando
Copy link

leemlwando commented May 12, 2018

Apparently, when the socket_handlers are placeD withing routes, they are called multiple times. Use the socket connection within app.js and require handlers within the socket connection, pass the socket as a parameter. Note that some properties may not be shipped together with the socket instance

@darrachequesne
Copy link
Member

@leemlwando please open a new issue if needed.

@meomar
Copy link

meomar commented Jun 13, 2018

I had the same problem what i did was to make a manual reconnect function on the client and call io.destroy(); inside the reconnect function this fixed the issue.

@Sivanesh-S
Copy link

Sivanesh-S commented Jun 24, 2018

Thanks a lot @leemlwando Your last comment made my solve my stuff.

@riteshsingh2k
Copy link

I am still getting this bug , is there any update ?

@DrLex0
Copy link

DrLex0 commented Jan 3, 2019

I think the only real bug here is that the internet is full of bad example code where socket.on() calls are wrapped inside the socket.on('connect') handler. Each time the socket reconnects, new instances of the handlers are stacked on top of the existing ones and this results in multiple calls upon each event. Don't do this: see @KasperTidemann's reply from 25 Jul 2012.

@ZiCog
Copy link

ZiCog commented Jan 19, 2019

Perhaps DrLexO, except the code I presented above demonstrated the problem. It has no socket.on() wrapped inside any socket.on('connect') handler.

After all these years I surprised to still be notified about this bug. I have no idea if it's a thing still or not. Do I have to try it again?

@Maverick-03
Copy link

@KasperTidemann thanks, it actually resolved the issue.

@michael-lynch
Copy link

How can you define your event listeners outside of the connect listener when you don't have access to the socket?

const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

io.on('connect', function(socket) {

  // only now that we are inside the connect callback do we have access to the socket

  socket.on('join', function(room, user) {
  });

  socket.on('add_message', function(room, user) {
  });

  socket.on('disconnect', function(room, user) {
  });
});

People seem to be suggesting that event listeners (join, add_message and disconnect) should live independently, outside the connect listener, but how is that possible without socket being defined?

io.on('connect', function(socket) {
  // socket is only available here
});

// socket is undefined here

socket.on('join', function(room, user) {
});

socket.on('add_message', function(room, user) {
});

socket.on('disconnect', function(room, user) {
});

Is there a different way to instantiate socket so that this is possible?

@bijanmmarkes
Copy link

Why is this closed? @michael-lynch has a valid point

@basickarl
Copy link

I would also like to know the answer to @michael-lynch's point.

@basickarl
Copy link

@DrLex0 on the socket.io website example it even shows to do the following:

io.on('connection', function(socket){
  socket.on('chat message', function(msg){
    io.emit('chat message', msg);
  });
});

@ghost
Copy link

ghost commented Jun 13, 2021

Is this problem solved. Does anyone has an answer to the issue. Because I am still getting this issue in 2021!

@LawrenceDarko
Copy link

Same issue here in 2022

@pushkarsingh019
Copy link

Still getting this issue

@yuran09
Copy link

yuran09 commented Dec 20, 2022

My client has implementation on Flutter framework and I'm having a similar situation. My app has 2 types of users, for one of them I made the socket to dispose in dispose() method and apparantly it isn't opening multiple sockets. The other user still have the problem

@abbasogaji
Copy link

still getting this

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests