youbetternot
youbetternot

Reputation: 2806

Socket.io not firing events properly after disconnecting

So I wanted to build a little game app with socket.io, it works like that:

User loads a website and I create a general socket using generalConnection namespace

app.generalSocket = io.connect('http://localhost/generalConnection');

I don't have any special events on it yet, but I thought it would be nice to keep it separate from a second namespace.

When the user logs in I call a function that starts game connection (another namespace) and bind some events to it, I won't list them all, I think it's not important.

app.startGameSocket = function() {
    app.gameSocket = io.connect('http://localhost/gameConnection'); //game connection

    app.gameSocket.on("connect", function() {
        console.log("connected to the game socket");
    });
}

On the server side I have something like that:

var connectedPlayers = [];
var gameConnection = io.of('/gameConnection').on('connection', function (socket) {
    socket.on('disconnect', function () {
        //some stuff
    });
});

Once again, I don't think I need to list all the events, I'll just explain how it works.

It listens to new player event, creates new player, pushes it connectedPlayers array and then sends it to everybody who is connected to gameConnection namespace.

User list is updated and everybody's happy. I can also listen to other events like disconnect and update the connectedPlayers array appropriately when user closes the browser window.

I also had to disconnect the gameConnection namespace when users log outs from the game, so on the client side I do:

app.vent.on('logOut', function() {
    app.gameSocket.disconnect();
)};

Notice that I keep generalConnection namespace open, I just disconnect the gameConnection namespace.

It works nice, if user logouts or closes window, disconnect event is triggered on the server side, connectedPlayers array is updated and sent back to connected players.

The problem

When user:

  1. Enters website.
  2. Logs in to the game.
  3. Logs out.
  4. Logs in again without refreshing window (triggers app.startGameSocket function again).
  5. And after all that closes the window, the gameConnection namespace disconnect event is not triggered on the server and list is not updated.

Node shell says stuff like: info - transport end (socket end) but not triggers the disconnect event. Please help :)

I tried to

app.vent.on('logOut', function() {
    app.gameSocket.emit('forceDisconnect'); //force disconnect on the server side
    app.gameSocket.disconnect();
    app.gameSocket.removeAllListeners(); //tried to really kill disconnected socket
)};

But no results.

Upvotes: 3

Views: 6345

Answers (3)

Harpreet Singh
Harpreet Singh

Reputation: 2671

How socket identifies various client connected to it is, via socket parameter while connection. Then all other other event gets assigned to each socket-client under io.connection block as socket.on. Whenever any client gets connected or disconnected its own socket event(socket.on) gets called and socket.io identifies it with that socket paramenter and id of each socket.

Sample

io.sockets.on('connection', function(socket //unique client socket as parameter) {
 //code block
}

Eg:

io.sockets.on('connection', function(socket) {
    //connect Me(socket)
    socket.on('connect', function() {
        console.log('disconnected')
    })
    //disconnect Me(socket)
    socket.on('disconnect', function() {
        console.log('disconnected')
    })
});

What your code doing is

app.vent.on('logOut', function() {
    app.gameSocket.emit('forceDisconnect'); //force disconnect on the server side
    app.gameSocket.disconnect();
    app.gameSocket.removeAllListeners(); //tried to really kill disconnected socket
)};

its not emitting disconnect event of client specific socket

app.gameSocket.emit('forceDisconnect'); //force disconnect on the server side

Force disconnect but disconnect whom?

You need something like this

app.startGameSocket = function() {
    app.gameSocket = io.connect('http://localhost/gameConnection'); //game connection

    app.gameSocket.on("connect", function() {
        console.log("connected to the game socket");
    });

    //disconnect
    app.gameSocket.on("disconnect", function() {
        console.log("disconnected");
        //force disconnect/logout code
    });

    app.gameSocket.on('logOut', function() {
        //force disconnect/logout code
        app.gameSocket.emit('forceDisconnect'); //force disconnect on the server side
        app.gameSocket.disconnect();
        app.gameSocket.removeAllListeners(); //tried to really kill disconnected socket
    )};

}

Upvotes: 1

youbetternot
youbetternot

Reputation: 2806

Socket.io is not so much fun!

In my app each log out > log in process was

app.gameSocket = io.connect('http://localhost/gameConnection'); //game connection

So calling it multiple times like that was causing problems. I've changed it to something like this:

app.firstConnect = true;

app.startGameSocket = function(){
    if(app.firstConnect){
        app.gameSocket = io.connect('http://localhost/gameConnection'); //game connection
    }else{
        app.gameSocket.socket.reconnect();
    }
}

app.vent.on('logOut', function(){
    app.firstConnect = false;
});

My issues are gone, but socket.reconnect introduces another! You can read about it here https://github.com/LearnBoost/socket.io/issues/430

Upvotes: 1

1nsane
1nsane

Reputation: 1047

You can configure socket.io to disconnect the connection on window unload.

See the sync disconnect on unload option of the client in the Socket.io wiki. This option defaults to false, so it should solve your problem if you enable it.

app.gameSocket = io.connect('http://localhost/gameConnection', {'sync disconnect on unload':true}); //game connection

Upvotes: 1

Related Questions