Reputation: 2180
I need to implement a system that is tolerant to occasional disconnections between client and server.
I understand that socket.io implements a HeartBeat ping pong thing that makes sure that a client is still alive and it times out after a certain amount of time.
I have two questions:
Is the disconnect event on the server side only called when the Heartbeat times out, say after 25 seconds or whatever or does it fire every time a client goes missing for a second?
In the case it fires every single time a client goes missing I was thinking of calling a setTimeout
in the disconnect
event handler that does the clean up after it had made sure that the client has not reconnected. Is that a good approach?
So in code it would be something like this:
socket.on('disconnect', function(){
setTimeout(cleanup, 8000);
});
function cleanup(){
if(socket.connected) return;
// clean up
}
Upvotes: 2
Views: 2038
Reputation: 10040
Is the disconnect event on the server side only called when the Heartbeat times out, say after 25 seconds or whatever or does it fire every time a client goes missing for a second?
The disconnect event is fired for the following reasons:
The server must receive a ping from the client every X milliseconds otherwise it disconnects the socket.
By default X = 5000 ms (5 seconds)
So the server expects the client to send a 'ping' every 5 seconds. By default the client will send a 'ping' every 2000 ms (every 2 seconds).
You can configure these values as follows:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http, {
pingInterval: 2000, // How many ms before the client sends a new ping packet
pingTimeout': 5000, // How many ms without a pong packet to consider the connection closed.
});
Comments are from the docs.
In the case it fires every single time a client goes missing I was thinking of calling a setTimeout in the disconnect event handler that does the clean up after it had made sure that the client has not reconnected. Is that a good approach?
The socket.io client has support for reconnection, so you should try this and see if works the way you want. Otherwise you can implement reconnection manually.
Here's how you configure reconnection on the client-side
io.connect('http://localhost', {
reconnection: true, // Whether to reconnect automatically (default: true)
reconnectionDelay: 500, // Number of reconnection attempts before giving (default: Infinity)
reconnectionAttempts: 10, // How long to initially wait before attempting a new reconnection (default: 1000)
});
Comments again taken from the docs. You find a few more options listed in the documentation.
Note that from the server's point of view a client reconnecting is a new client. I don't think it has any understanding that it is a disconnected client coming back.
So I'd say the simple solution is to cleanup immediately (with no setTimeout) and let the system handle any reconnection as if it were a new socket.
If the cleanup is somekind of cache, and it's very expensive to regenerate the cache, then maybe you do want to try and reuse the cache for a client that reconnects. In that case you might want to generate a GUID in your client that you pass to the server when client connects or reconnects so that your server can re-identify the reconnected socket and reattach it to it's cached data record. This is going to get messy, best to stick with the simple solution if you can.
Another approach might be to garbage collect the cache every so often instead of doing the setTimeout. Keep a record (in the cache) of whenever it was last used by a client. Every 30 minutes (or whatever interval you choose) go over the cache and remove records for clients that haven't been seen for a while. You need to use the GUID approach in this case as well so that reconnecting clients can reattach to their cached records.
Upvotes: 4