Fleck: Disconnecting Clients Not Triggering OnClose
I want to make sure that certain code get’s executed when a connection is closed (could be for various reasons, sudden power loss, network disconnection, shut down). For some reason, only some of my connections trigger the OnClose event, while others don’t at all. Then the next problem that stems from this is that when a client tries to reconnect, it can’t because the Server believes that there is already a websocket connection with that computer.
The reason I know that the OnClose event is not being triggered is because some clients still show up as true when I call .IsAvailable on the sockets (I have a list of sockets that I periodically check to see if they are available and update online/offline statuses based off of them). Seems to me this happens most when a computer is shutdown.
About this issue
- Original URL
- State: open
- Created 10 years ago
- Comments: 37 (10 by maintainers)
Apologies for jumping in here, but I think it is important to understand the design, operation, and limitations of the underlying technology WebSockets are based on. Please pause a moment and read this: http://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html and this http://stackoverflow.com/questions/722240/instantly-detect-client-disconnection-from-server-socket Furthermore, perhaps some background on the WebSocket protocol - I find this link useful: http://lucumr.pocoo.org/2012/9/24/websockets-101/
Once you understand the above links, it becomes apparent why it is not possible to implement a 100% reliable OnClosed in Fleck (or any other library) unless you want to pollute the WebSocket protocol. Any library will give you clean socket close notifications, because they are practically free and very useful. For unclean closes? You’d need to send ping/pongs in the library, even when you are in an otherwise idle state. If you were to go this far, then how often? Every 1 second? 1 hour? 50 Milliseconds? That is going to vary based on need of application. Then how long should it wait for a Pong? That number may be client application based. This is FAR too much for a protocol like WebSockets to worry about. How you USE the WebSocket protocol must be based on your needs.
The WebSocket protocol specifies Pings and Pongs on both sides - the receiver of a ping responds to a pong ‘as soon as practical’ at the underlying websocket level and you do not need to write anything special into your subprotocol to handle it. On the server side, send a Ping at whatever interval is your minimum threshold for detecting a disconnect - if no response after a reasonable time, it is bad and should be closed on your side.
Where this can break down is if it is important the Client must detect a broken connection within some interval. Some clients (think browsers) don’t expose a mechanism to send a ping, or know that a ping was received, so you have to implement a heartbeat message the clients can send that you respond to in your subprotocol. When you do this, on the server side you can avoid sending pings if you got a heartbeat within a certain time period to be as resource efficient as possible. If you are implementing this heartbeat, I’d suggest that you implement something else in your subprotocol where the server can specify the heartbeat interval that the client (should) obey. This way you can change it server side as necessary if it becomes too chatty, and your logic of send ping if heartbeat not received in ‘X’ time can be coordinated.
Here is a link to someone that implemented a heartbeat message so a Javascript client could detect a stale connection - I’m not necessarily recommending it, but more as a real life example: http://django-websocket-redis.readthedocs.org/en/latest/heartbeats.html
I hope this was useful to someone!