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

The right way for a client to reconnect after the server does a socket.disconnect( true ) #2476

Closed
DrLightman opened this issue Mar 9, 2016 · 35 comments

Comments

@DrLightman
Copy link

Server: node + socket.io

var io = require( 'socket.io' )( 3000 );

io.on( 'connection', function ( socket ) ...

// at some point if client auth fails, server may kick him out:

socket.disconnect( true );

Client: html/js + socket.io 1.4.5

socket = io.connect( 'http://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: 99999
} );

socket.on( 'connect', function () {
    console.log( 'connected to server' );
} );

socket.on( 'disconnect', function () {
    console.log( 'disconnected to server' );
} );

The above is simplified but that is the basis. Reconnection works fine if I fire up the client when the server is down. The client tries to connects to the server and when I finally fire up the server the connection is estabilished.

At some point it may happen that the server decides to disconnect the client, mainly because he logged out invalidating the token and a query on the db tells to do so, or the auth token expired or whatever.

IN this circumstance I'd like the restore the server polling by the client because the user may want to login again and he has the rights to connect again to the server.

If I refresh the page (client) in the browser it works okay but it's an ugly solution.

I think the cause is the "Manager.skipReconnect" property set to true after doing disconnect(), so I'm asking what is the proper way to reinitiate a reconnection polling by the client after the server disconnects a client.

Found some answers on stackoverflow about this but all were unsuccessfull, all stuff to be executed in the client:

  • socket.io.reconnect();
  • socket.socket.reconnect(); // ??
  • socket = io.connect( 'http://127.0.0.1:3000', ... // reinvoking the connect snippet seems bad idea

Could you help me about this matter?

Thank you

@DrLightman DrLightman changed the title The right way of reconnecting after the server does a socket.disconnect( true ) The right way for a client to reconnect after the server does a socket.disconnect( true ) Mar 9, 2016
@DrLightman
Copy link
Author

For now, I managed this way and it seems to be stable:

Client:

var app = {
...
socket: null,
connect: function() {
  var self = this;
  if( self.socket ) {
    self.socket.destroy();
    delete self.socket;
    self.socket = null;
  }
  this.socket = io.connect( 'http://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );
  this.socket.on( 'connect', function () {
    console.log( 'connected to server' );
  } );
  this.socket.on( 'disconnect', function () {
    console.log( 'disconnected from server' );
    window.setTimeout( 'app.connect()', 5000 );
  } );
}
...
} // var app

@JamieMeyer
Copy link

Using a similar approach of:

  this.socket = io.connect( 'ws://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );

Unfortunately, this causes the socket to use http protocol, rather than web sockets.

Still seeking a good approach for a persistent web socket connection.

Have I missed something???

@JulesAU
Copy link

JulesAU commented Nov 11, 2016

Also interested in a solution to this.

@sconway
Copy link

sconway commented Dec 4, 2016

socket.connect()
worked for me on version 1.5.1 . Hope that helps.

@husnulhamidiah
Copy link

@sconway Can you enlighten us? Any code may be?

@wiill
Copy link

wiill commented Mar 9, 2017

Hi there,

Had the same question, found this solution, currently testing, seems to be either a robust solution or a robust workaround... (both are provided)

http://stackoverflow.com/questions/10437584/socket-io-reconnect

@ramtob
Copy link

ramtob commented Jul 2, 2017

Could we get this fixed in socket.io itself?

@trentkg
Copy link

trentkg commented Jul 14, 2017

I upgraded to version 2.0.3 and its default autoreconnect settings worked, no issues here.

@pablodgonzalez
Copy link

pablodgonzalez commented Jul 21, 2017

When whether Server or Client calls to disconnect() method the client destroy the socket, deletes all events handlers and the manager removes it from the connecting array. This won't occurs when the disconnection is for another reason.
A great workaround could be read the reason parameter

.on('disconnect', reason => { 
  if(reason === 'io server disconnect') {
    //you should renew token or do another important things before reconnecting
    socket.connect();
  }
});

Or much better check if socket still be in the manager's connecting list

.on('disconnect',  () => {
  if(socket.io.connecting.indexOf(socket) === -1){
    //you should renew token or do another important things before reconnecting
    socket.connect();
  }
})

@jimping
Copy link

jimping commented Aug 3, 2017

I did it like @DrLightman and it works perfectly!

var WebSocketServer = {
	isConnected: false,
	socket: null,
	interval: null,
	connect() {
		if (this.socket) {
			this.socket.destroy();
			delete this.socket;
			this.socket = null;
		}
		this.socket = io.connect('http://localhost:9010', {
			reconnection: false
		});
		this.socket.on('connect', () => {
			this.isConnected = true;
			this.socket.emit('authentication', { user_id: 2751, token: "abc" });
			this.socket.on('authenticated', function() {

			});
		});

		this.socket.on('disconnect', () => {
			this.isConnected = false;
			this.interval = window.setInterval(() => {
				if (this.isConnected) {
					clearInterval(this.interval);
					this.interval = null;
					return;
				}
				WebSocketServer.connect()
			}, 5000);
		});

		return this.socket;
	}
}

var socket = WebSocketServer.connect();

@devyaz
Copy link

devyaz commented Nov 24, 2017

@DrLightman this is how i do it and works perfectly in browsers or Android/IOS Apps
var io= new socketio.connect('http://192.168.43.79:3000',{'forceNew':true});

@programmerCs
Copy link

@pablodgonzalez i have same question ,your solution is worked?

@pablodgonzalez
Copy link

@programmerCs Yes, It is. In production without detected problems.

@chiragiem36
Copy link

This issue cleared a lot of my issues
Thanks everyone

@wmcmurray
Copy link

Had the same problem when I wanted to force a client to refresh it's token because it expired while connected to the server.

I ended up sending an event to the client instead, asking him to refresh it's token. No socket gets closed by doing this, so it avoids problems and it works fine !

...now it's time to push that to production ! 😰 😏

@qassa
Copy link

qassa commented Jan 31, 2018

Seems like the simpliest solution is to listen to 'disconnect' event from emitter and call setTimeout( ) function but what about events which the client can create while it's being disconnected from the server? Seems like it needs always to execute additional check if connection is established before broadcasting any emit on client.

@pablodgonzalez
Copy link

@qassa if you need some confirmation about emit, you should use callback parameter. Instead if you need guarantee the reception of an event, you should not use socket.io but some queue library/protocol such as mosquito/mqtt or whatever.
the setTimeout is an option but a socket disconnected (by the server or the client) is a socket soon destroyed. So, if you need guarantee easy and fast reconnection why use setTimeout if you have the socket object instance yet and can call connect()?

@CxRes
Copy link

CxRes commented Feb 1, 2018

Someone from the project REALLY NEEDS TO DOCUMENT this...

@devyaz
Copy link

devyaz commented Feb 2, 2018 via email

@paredesivan
Copy link

@devyaz i love you

@darrachequesne
Copy link
Member

The documentation was updated with @pablodgonzalez 's answer: socketio/socket.io-client@afb952d

Thanks a lot!

@pankajtalaviya97
Copy link

Use 0.8.3 version of io.socket remove new version 1.0.0

compile('io.socket:socket.io-client:0.8.3') {
    exclude group: 'org.json', module: 'json'
}

@blubbll
Copy link

blubbll commented Oct 19, 2018

Using a similar approach of:

  this.socket = io.connect( 'ws://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );

Unfortunately, this causes the socket to use http protocol, rather than web sockets.

Still seeking a good approach for a persistent web socket connection.

Have I missed something???

use wss://

@knightchim
Copy link

Using a similar approach of:

  this.socket = io.connect( 'ws://127.0.0.1:3000', {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax : 5000,
    reconnectionAttempts: Infinity
  } );

Unfortunately, this causes the socket to use http protocol, rather than web sockets.
Still seeking a good approach for a persistent web socket connection.
Have I missed something???

use wss://

hello,bro.how can be that if just use wss.it just work as persistent web socket connection,have same question about just keep and fast reconnet with ws not polling.

@emclab
Copy link

emclab commented Apr 16, 2019

When whether Server or Client calls to disconnect() method the client destroy the socket, deletes all events handlers and the manager removes it from the connecting array. This won't occurs when the disconnection is for another reason.
A great workaround could be read the reason parameter

.on('disconnect', reason => { 
  if(reason === 'io server disconnect') {
    //you should renew token or do another important things before reconnecting
    socket.connect();
  }
});

Or much better check if socket still be in the manager's connecting list

.on('disconnect',  () => {
  if(socket.io.connecting.indexOf(socket) === -1){
    //you should renew token or do another important things before reconnecting
    socket.connect();
  }
})

Can you elaborate why it is better to check if the socket is still in manager's connecting list? The updated doc only took your first solution which is to check the reason for disconnect. Thanks.

@pablodgonzalez
Copy link

Hi @emclab, just because if in newer version the developers add some new reason, and for your case is not important "the reason" then just search for the socket in the connection list. if it is not there, so you have to reconnect manually.
In some cases is important know the reason, and is the more powerful case, read and act accordingly but maybe is not the most common.
Disclaimer: if you go for the second way, you are not safe of refactors or some changes in mechanisms in newer versions, so it is not much better but much simpler.
regards!

@krunal9421
Copy link

I am not able to socket disconnect into ionic application. I have socket.on into the constructor of common page in providers. I want to disconnect socket into a function on the same file from where application logout is called.

But I am able to disconnect the socket. I am multiple socket.on('event') on multiple emit into application.
Can any one help me out?

@devyaz
Copy link

devyaz commented Nov 14, 2019 via email

@krunal9421
Copy link

@devyaz I am unable to disconnect the socket using socket.disconnect().
I have sharing my sample code with this.
https://i.stack.imgur.com/wrIEv.png.

I have written code into common file.

@devyaz
Copy link

devyaz commented Nov 22, 2019 via email

@krunal9421
Copy link

using this on client side.

@devyaz
Copy link

devyaz commented Nov 26, 2019 via email

@Aye-Myat-Mon
Copy link

Aye-Myat-Mon commented Jul 14, 2020

After losing connection, socket reconnects to the server. After that, it keeps showing io.socket.engineio.client.EngineIOException: xhr post error in Android .
Most of the answers from StackOverflow don't work.
I'm stuck with this issue T_T.... Help me please!

@asiermusa
Copy link

asiermusa commented Nov 14, 2020

I am trying to implement this code in my node.js + javaScript wepapp but when the browser of my phone is in the background, in an inactive tab or locked screen it is disconnected after some minutes.

I tried to reconnect to a socket when it is disconected (with ping timeout or transport closed responses) but it is impossible. Is this a normal behaviour on phone browsers? because in laptop or desktop browsers works as expect.

Can anyone help me?

Thanks

@pablodgonzalez
Copy link

Hi @asiermusa but in web you must use a web-worker to avoid suspend the process. I sincerely I don't known if it is enough to achieve that.

cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests