Disconnect event gets fired 2 minutes later - node.js

I'm using Node.JS and Socket.IO to create a chat, I use XHR polling with a duration of 10 to host it on Heroku.
When I leave the page with my client, I'd like to calll the disconnect method automatically on the server which removes it from other clients. It's in fact done but... 2 minutes after the client has really left the page, which is quite awkward.
Is there a way to call the disconnect method as soon as the client doesn't reply ? Or at least being a little faster to know when the client is not there anymore ?
I've tried to close the socket client-side on page exit with jQuery but it doesn't work. The problem is that using socket.disconnect() is asynchronous and non-blocking and the user leaves before the request is completed...

You can play with heartbeat timeout, heartbeat interval and close timeout values of socket.io configuration.
Search for heartbeat and timeout in this page: https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO

If you set the 'sync disconnect on unload' option on the socket.io client to true, it will send a synchronous xhr disconnect request in onbeforeunload that will disconnect the socket.

Related

socket.io force a disconnect over XHR-polling

I have a client/server application using nodejs on the server and socket.io as the connection mechanism. For reasons relevant to my application I want to have only one active connection per browser, and reject all the connections from other tabs that may be opened later on during the session. This works great with WebSockets, but if WebSockets is not supported by the browser and XHR-polling is used instead, the disconnection never happens, so if the user just refreshes the page, this is not interpreted as a reconnection ( I have a delay for reconnection and session restoring), but as a new tab, which ends in the connection being rejected because the old connection made by this same tab is still active.
I'm looking for a way to effectively end the connection from the client whenever a refresh occurs. I've tried binding to the beforeunload and calling socket.disconnect() on the client side, and also sending a message like socket.emit('force-disconnect') and triggering the disconnect from the server with no success. Am I missing something here? Appreciate your help!
I've read this question and couldn't find it useful for my particular case.
Solved the issue, it turns out it was a bug introduced in socket.io 0.9.5. If you have this issue just update BOTH your server and client-side code to socket.io > 0.9.9 and set the socket.io client-side options sync disconnect on unload to true and you're all set.
Options are set this way:
var socket = io.connect('http://yourdomain.com', {'sync disconnect on unload' : true});
You can also get "Error: xhr poll error" if you run out of open file descriptors available. This is likely to happen during a load test.
Check the current open file descriptor size:
ulimit -n
Increase it to a high number:
ulimit -n 1000000

negative ack from socket.io

I am using socket.io to send data from my sever to clients. There are situations when a client looses its connection but the server gets to know about this only when the next heartbeat is not recieved from the ckient.
the messages that are sent between the client loosing its network connection to the time when the sever derives this from absense of heartbeats are lost and I am not able resend them when the client rconnects.
I know there I can send a callback in my message which the client will call on successfull delivey of message. however this callback is asynchronous and I Am not aware of any way by which I can getto know that the message delivery failed. Can anyone please help me findhow can I capture a failure to delive a message.
Thanks in advance
According to the documentation, you can configure "max reconnection attempts" for
How many times should Socket.IO attempt to reconnect with the server after a a dropped connection. After this we will emit the reconnect_failed event.

Socket.io delay in firing the "disconnect" event?

I have a socket.io client connected to a node.js server. If I kill node.js at the command line, the client immediately freezes (i.e., communication stops), but there is a ~20 second delay before the "disconnect" event is fired. Is this behavior by design? Is there a configuration option to reduce the delay in firing the disconnect event?
It appears that this behavior changed in a relatively recent (last 6 months) update of socket.io. Before the reconnect functionality was built in to socket.io itself, I implemented my own reconnect logic using a "disconnect" event handler and at that time the "disconnect" event fired almost instantly when server communication halted.
I think this is likely a design pattern. The client may be presuming the server is 'temporarily' unreachable (network trafic etc) and essentially will keep trying to reach it... until the client timeout kicks in.
I send a disconnect (socket.disconnect()) to the server directly from the client, and I don't get this issue.

Advantage/disadvantage of using socketio heartbeats

Socket.io allows you to use heartbeats to "check the health of Socket.IO connections." What exactly are heartbeats and why should or shouldn't I use them?
A heartbeat is a small message sent from a client to a server (or from a server to a client and back to the server) at periodic intervals to confirm that the client is still around and active.
For example, if you have a Node.js app serving a chat room, and a user doesn't say anything for many minutes, there's no way to tell if they're really still connected. By sending a hearbeat at a predetermined interval (say, every 15 seconds), the client informs the server that it's still there. If it's been e.g. 20 seconds since the server's gotten a heartbeat from a client, it's likely been disconnected.
This is necessary because you cannot be guaranteed a clean connection termination over TCP--if a client crashes, or something else happens, you won't receive the termination packets from the client, and the server won't know that the client has disconnected. Furthermore, Socket.IO supports various other mechanisms (other than TCP sockets) to transfer data, and in these cases the client won't (or can't) send a termination message to the server.
By default, a Socket.IO client will send a heartbeat to the server every 15 seconds (heartbeat interval), and if the server hasn't heard from the client in 20 seconds (heartbeat timeout) it will consider the client disconnected.
I can't think of many average use cases where you probably wouldn't want to use heartbeats.

Weird Socket.IO behavior: events "on connection" and "on disconnect" happen almost at the same type

On the socket io server I have something like:
io.sockets.on('connection',function(client) {
console.log(client.id + ' connected at '+(new Date()).getTime());
client.on('disconnect',function() {
console.log(client.id + ' DISCONNECTED at '+(new Date()).getTime());
});
});
And my problem is that this happens:
debug - client authorized
info - handshake authorized 15229479751557595508
debug - setting request GET /socket.io/1/websocket/15229479751557595508
debug - set heartbeat interval for client 15229479751557595508
debug - client authorized for
debug - websocket writing 1::
15229479751557595508 connected at 1313769716321
debug - websocket received data packet 5:::{"name":"estimatepp","args":[9]}
debug - websocket received data packet 5:::{"name":"ready","args":[null]}
info - transport end
debug - set close timeout for client 15229479751557595508
debug - cleared close timeout for client 15229479751557595508
debug - cleared heartbeat interval for client 15229479751557595508
15229479751557595508 DISCONNECTED at 1313769716454
debug - discarding transport
I don't know if this is normal but as you can see, the client 15229479751557595508 connects at 1313769716321 and disconnects at 1313769716454, just 133 mili-seconds later (this number is always either 132 or 133). I'm not ordering the client to disconnect after something.
Any ideas on why does this happen ?
Also I have another doubt. If I listen for connection events on io.sockets.on, shouldn't I be listening for disconnect events also there ? Except there's no client there...
What is the correct way to listen for disconnections ?
Thanks for any help.
EDIT: You can ignore the lines
debug - websocket received data packet 5:::{"name":"estimatepp","args":[9]}
debug - websocket received data packet 5:::{"name":"ready","args":[null]}
It's part of the project I'm working on. Maybe the thing is that it just receives those events and after that because there's no activity for a while it closes the connection ? But this is not wanted behavior is it ?
The server-side code that you have posted is fine and should work as expected. Check for bugs in your client-side code (or post your client-side code here). If nothing there, try a different browser.
Regarding your disconnect event.
You have an io.sockets.on("connection", function (client) { ... }) event handler where when a new connection is made, a session is created for the connection and is stored in the client variable.
You then attach event handlers (like the disconnect one) to this client object.
Now when that client disconnects, the disconnect event handler attached to that particular client object is invoked.
Moreover, as you can see in Exposed Events — Socket.io, io.sockets.on only exposes the connection event.
I have similar thoughts as the creator of the question.
The time in ms is probably your roundtrip time to the server or the time it takes to manage connects with the client etc etc. So I wouldnt bother so much with the time factor.
I get same result when I refresh the client manually and repeatedly. between say half and one second intervals. This seems to create a scenario which otherwise only happen with poor network quality.
I can see in the logs that I get a connection, before a disconnection with the same socket.id.
client connected: qEcxQQCivSyKJVbF85dc
client disconnected: qEcxQQCivSyKJVbF85dc
However my on.disconnect event does in this scenario NOT fire.
On disconnects I clean up my local object of connected clients and I can see that I a client left in there and when I analyze the socket.connected status it is disconnected.
So under certain circumstances the above scenario causes a disconnect event to not fire.
Probably due to timings, asynch, network quality etc.
Two ways to go.
Build the application according to those constraints or
find someone who can come up with a more solid method for listening to on.disconnect, which, as the original question eluded, does not involve being attached to a specific socket client.
It is like the event listener is overwritten when the client connects again with the same id. A more general disconnect event listener would disregard that but potentially cause other issues instead.
I am personally going with option 1. and instead creating a garbage collector of sorts that clean up my local array of clients if they are disconnected.

Resources