Lionel Chan
Lionel Chan

Reputation: 8059

How to reconnect after you called .disconnect()

Question: How do you reconnect a client to the server after you have issued a manual .disconnect()?

In my current project, I need to disconnect a client from the server when the user log out from the session. I did a socket.disconnect() to do the disconnection successfully. Server removed the user from the session.

After awhile, the user decided to login again, but socket.io refuses to connect.

I am clear that Socket.IO has implemented reconnection algorithm but clearly this is a different case.

Below is the piece of code where I do the connection. On second trigger of this block of code, object socket was created, but no connect was fired from this object.

//Start the socket
var socket = io.connect(SOCKET_IO_URL);
socket.on('connect', function() {
    me.fireEvent('connect');
    socket.emit('register', {
        hashed_identifier: hashed_identifier,
        account_id: account_id
    });
});

socket.on('ready', function() {
    me.ready = true;
    me.log('Handshake done. Listening for new data');
});

socket.on('data', function(data) {
    me.fireEvent('data', data);
    //Tells server we received it
    socket.emit('data', {ack: 1});
});

socket.on('disconnect', function() {
    me.fireEvent('disconnect');
});

UPDATE: As requested by @Tony

In fact the whole thing is wrapped under Sencha Touch 2.0, but I believe there is nothing to do with ST2.0

This is my Data Class. Usage of this class is when the user logged in, this class will get initialized. And upon the user logout, the system will call the disconnect() method in this class.

When the user login again, this class is initialized again, but funny is the socket somehow retained all the previous events and sessions it has previously.

/**
* Serve as interface to wait for data communication in between server and client
*/
Ext.define('go.module.connect.Data', {

    mixins: {
        observable: 'Ext.mixin.Observable'
    },

    config: {
        account: null
    },

    ready: false,

    socket: null,

    constructor: function(cfg) {
        var me = this,
            hashed_identifier = Sha1.hash(go.__identifier);


        me.initConfig(cfg);

        var account_id = me.getAccount().get('id');

        //Start the socket
        var socket = io.connect(SOCKET_IO_URL);
        socket.on('connect', function() {
            console.log('connect');
            me.fireEvent('connect');
            socket.emit('register', {
                hashed_identifier:hashed_identifier,
                account_id: account_id
            });
        });

        socket.on('ready', function() {
            me.ready = true;
            me.log('Handshake done. Listening for new data');
        });

        socket.on('data', function(data) {
            me.fireEvent('data', data);
            //Tells server we received it
            socket.emit('data', {ack: 1});
        });

        socket.on('disconnect', function() {
            me.fireEvent('disconnect');
        });

        console.log(socket);
        if (!socket.socket.connected){
            socket.socket.reconnect();
        }


        me.socket = socket;


        me.callParent([cfg]);
    },

    disconnect: function() {
        this.socket.disconnect();
        this.socket.removeAllListeners();
        this.socket.socket.removeAllListeners();
    },

    log: function(msg) {
        console.log('@@ Connect: '+msg);
    }
});

And below is my console.log results:

Console screenshot

And below is my node.js debug window

Node.js debug window

I believe the root cause of this funny scenario is that the previously attached connect event listener is not removed thoroughly. How should I remove it? Should I use once? or I should specify the listener function as well. I thought removeAllListeners() is sufficient for this task.

Upvotes: 8

Views: 23424

Answers (7)

Tony Abou-Assaleh
Tony Abou-Assaleh

Reputation: 3040

The standard approach in latest socket.io is:

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

This is what I've been using in my app and works great. It also ensures that the socket keeps trying to reconnect if the server goes way, and eventually reconnects when the server is back online.

In your case, you need to ensure two things:

  1. You create your socket only once. Don't call socket = io.connect(...) more than once.
  2. You setup your event handling only once - otherwise they will be fired multiple times!

So when you want to reconnect the client, call socket.socket.reconnect(). You can also test this from the browser console in FireFox and Chrome.

Upvotes: 16

Mathias Osterhagen
Mathias Osterhagen

Reputation: 424

socket.io v2.0 (current)

For the peoples that was looking as me for the last version please find the doc extract as below:

To manually reconnect:

socket.on('disconnect', () => {
  socket.open();
});

Upvotes: 1

Isaac Pak
Isaac Pak

Reputation: 4931

socket.io-client v2.2.0

import io from "socket.io-client"

var socket = io(url)  // initial connection

const reconnect = () => {
  if(!socket.connected) {
    socket = io(url)  // reconnects to a new socket
  }
}

Upvotes: -1

DrLightman
DrLightman

Reputation: 673

I'm doing this way with socket.io 1.4.5 and it seems to work, for now:

var app = {
    socket: null,
    connect: function() {
      // typical storing of reference to 'app' in this case
      var self = this;
      // reset the socket
      // if it's not the first connect() call this will be triggered
      // I hope this is enough to reset a socket
      if( self.socket ) {
        self.socket.disconnect();
        delete self.socket;
        self.socket = null;
      }
      // standard connectiong procedure
      self.socket = io.connect( 'http://127.0.0.1:3000', { // adapt to your server
        reconnection: true,             // default setting at present
        reconnectionDelay: 1000,        // default setting at present
        reconnectionDelayMax : 5000,    // default setting at present
        reconnectionAttempts: Infinity  // default setting at present
      } );
      // just some debug output
      self.socket.on( 'connect', function () {
        console.log( 'connected to server' );
      } );
      // important, upon detection of disconnection,
      // setup a reasonable timeout to reconnect
      self.socket.on( 'disconnect', function () {
        console.log( 'disconnected from server. trying to reconnect...' );
        window.setTimeout( 'app.connect()', 5000 );
      } );
    }
} // var app


app.connect();

Upvotes: 2

Prasad Bhosale
Prasad Bhosale

Reputation: 722

You can reconnect by following client side config.

 // for socket.io version 1.0
io.connect(SERVER_IP,{'forceNew':true };

Upvotes: 2

JT.
JT.

Reputation: 33

It seems to me it is how you handle the disconnect... Worked for me using socket.io - v1.1.0

wrong way...

var sock = io( '/' );
sock.on( 'connect', function(x) { console.log( 'Connected', x ); } );
// now we disconnect at some point:
sock.disconnect();
// now we try to reconnect...
sock.connect()
// or    
sock.reconnect();
// - both seem to create the new connection in the debugger, all events are missing though

correct way...

// As above with 3 extra characters, everything functions as expected...
//events fire properly...
sock.io.disconnect();
// consequently i'm also using (for consitency)
sock.io.reconnect();
// sock.connect() still seems to work however.

Upvotes: 1

Saurabh Kumar
Saurabh Kumar

Reputation: 135

socket.socket.connect();

gets you reconnected.

Upvotes: 2

Related Questions