Socket.io: The right way for a client to reconnect after the server does a socket.disconnect( true )

Created on 9 Mar 2016  ·  35Comments  ·  Source: socketio/socket.io

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

Most helpful comment

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

All 35 comments

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

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???

Also interested in a solution to this.

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

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

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

Could we get this fixed in socket.io itself?

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

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(); } })

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();

@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});

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

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

This issue cleared a lot of my issues
Thanks everyone

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 ! :cold_sweat: :smirk:

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.

@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()?

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

Lemme get this straight, does the server disconnect the client for a specific reason or due to loss of network connection? If its just network then Socketio(client) will try indefinitely to re-connect! , if configured like this io=new socketio(‘http://yourserver.com’, {'forceNew':true}); either way it will still reconnect, but if you put a listerner to a disconnect from server, simply call io.disconnect() on client

From: CxRes [mailto:[email protected]]
Sent: February 01, 2018 09:50 PM
To: socketio/socket.io socket.io@noreply.github.com
Cc: devyaz mtunthama@gmail.com; Comment comment@noreply.github.com
Subject: Re: [socketio/socket.io] The right way for a client to reconnect after the server does a socket.disconnect( true ) (#2476)

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


You are receiving this because you commented.
Reply to this email directly, view it on GitHub https://github.com/socketio/socket.io/issues/2476#issuecomment-362381171 , or mute the thread https://github.com/notifications/unsubscribe-auth/ATfQSQQ1LJ90E6FqsdmiMktpp2AdoLuxks5tQhVQgaJpZM4HsVs7 . https://github.com/notifications/beacon/ATfQSYqwkgtrHZk9FASNZUl69ps9ZYYCks5tQhVQgaJpZM4HsVs7.gif

@devyaz i love you

The documentation was updated with @pablodgonzalez 's answer: https://github.com/socketio/socket.io-client/commit/afb952d854e1d8728ce07b7c3a9f0dee2a61ef4e

Thanks a lot!

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'
}

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://

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.

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.

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!

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?

Socket.disconnect() should do

On Mon, 11 Nov 2019 06:16 krunal9421, notifications@github.com wrote:

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?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASNI2K4DWOB4P2HPSATQTDMC7A5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEDVTS3A#issuecomment-552286572,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AE35ASJPORGOSYQAEJEHHG3QTDMC7ANCNFSM4B5RLM5Q
.

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

Are you trying to disconnect from server or user side? i.e server should
disconnect user. Because if server loses the client, it fires a disconnect
event. But client can disconnect from server by calling
socket.disconnect

On Wed, 20 Nov 2019 05:39 krunal9421, notifications@github.com wrote:

@devyaz https://github.com/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.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASK4NY4SKG5JWSBDKCTQUSWNVA5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEEQS5AI#issuecomment-555822721,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AE35ASIFTISGTIAQQ7UKCJDQUSWNVANCNFSM4B5RLM5Q
.

using this on client side.

Do this.socketstatus.disconnect() in your logout function and I think
you should remove the function ".on("connected",.....)"

On Fri, 22 Nov 2019 11:50 krunal9421, notifications@github.com wrote:

using this on client side.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/socketio/socket.io/issues/2476?email_source=notifications&email_token=AE35ASJTREAYRMF4THBK3FDQU6TOLA5CNFSM4B5RLM52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEE5EHCI#issuecomment-557466505,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AE35ASJGKVGVUQNK454C63DQU6TOLANCNFSM4B5RLM5Q
.

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!

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

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!

Was this page helpful?
0 / 5 - 0 ratings