Theldus / wsServer

wsServer - a tiny WebSocket server library written in C
https://theldus.github.io/wsServer
GNU General Public License v3.0
422 stars 80 forks source link

Close Event Not Always Firing on Server #71

Closed CycloneRing closed 10 months ago

CycloneRing commented 1 year ago

Hi @Theldus, I made a tiny game server using your amazing library, I did entire development on localhost and yesterday I got a VPS to run it on real server.

A weird bug happens when I'm using wsServer on VPS, when clients disconnect from server it doesn't always fire onclose it happens randomly like 1 in 5, I have no idea why is this happening and why it only happens on VPS and not localhost.

Do you have any idea how can I fix it? I toke a look at source code it seems neat and fine but still it happens.

I'm using Windows Server 2019

Theldus commented 1 year ago

Hi @CycloneRing, I don't know exactly under what conditions your clients are disconnected, but if it's abrupt and unexpected, it can happen that the connection doesn't close immediately (and this happens at the OS level).

On issue #50 I explain better about these cases, but basically:

Devices that are able to sleep or situations where there is an abrupt drop in connection (such as a weak WiFi signal) can cause the socket to not close immediately, even if the device is unable to receive messages from the server.

Situations like this make wsServer keep these devices in the clients list, even if they are virtually disconnected from the server, this causes:

  • ws_sendframe*() try to send messages to them during broadcasts
  • send() to them returns as if the message had been sent
  • occupy limited slots of the client list and also other server resources

For these scenarios you might want to send a PING packet occasionally, to detect this type of failure and abort these connections, you can check out a working example at ping.c.

However, if your connections are closing normally (with a close packet) and not being detected, this is a problem that needs to be fixed.

... when clients disconnect from server it doesn't always fire onclose it happens randomly like 1 in 5, I have no idea why is this happening and why it only happens on VPS and not localhost.

1 out of 5 is a pretty high number... do you notice that too if you run something simpler? like the echo example?

And what causes your clients to disconnect? Are you sending a client-side ws.close() or similar?

CycloneRing commented 1 year ago

Hi, Thank you for detailed answer, I close the connection but I want to close it if game crashes as well because my game doesn't allow one account play on two device at same time, So untill connection is alive server holds data that Account is in use. And when this disconnection bug happensm on both ws.close and app crash, Server keep account alive and it cause problem, On localhost it works perfectly.

I had this idea to flag all connected sockets each 5 seconds and notify them to send back a heart beat, If they don't send heart beat back server kick them out, But this can be very hard and confusing to implement in terms of multi-threading.

Theldus commented 1 year ago

Hi, I still don't understand for sure, does this problem occur even when the client disconnects properly?

I had this idea to flag all connected sockets each 5 seconds and notify them to send back a heart beat, If they don't send heart beat back server kick them out, But this can be very hard and confusing to implement in terms of multi-threading.

This is essentially the idea behind the PING packets that wsServer natively supports. In the example I gave you before (ping.c), the server sends a PING packet every 10 seconds, if the client does not respond with a PONG between 2 PINGs, the server itself closes the connection with the client and the on_close() is called normally.

All the logic is already contained there in ping.c, no need to manage threads or anything: just run ws_ping() periodically.

Theldus commented 10 months ago

As there is no further response, I will close. Feel free to add any extra information if you feel necessary =).