websocket-client icon indicating copy to clipboard operation
websocket-client copied to clipboard

Disconnection detection

Open dinos19 opened this issue 2 years ago • 3 comments

Hello , im a junior .net developer and there is a thing that i cannot understand so i need your help. Im working on an app with video calls , txt msges etc. The problem is when im disconnected it wont detect it sooner than 15+ seconds. I tried changing ReconnectTimeout but it invokes DisconnectionHappened and then ReconnectionHappened which is not good. i read about keepaliveinterval, tried to change it to 2 millisecond to test it out but nothing changed.Also reconnection takes too long to happen, if i remove ethernet for 2 seconds it ll take up to 15seconds to detect connectivity. any suggestion ?

edit : i reduced the ReconnectTimeout and handle it depending on the type but still reconnection takes too long. also tried adding the options with KeepAliveInterval set to 2 seconds but still didnt help.

dinos19 avatar Jul 30 '21 10:07 dinos19

Hello @ dinos19,

that issue of late disconnected info is caused by some lower level, .NET framework or probably even OS.

So we can't do much about it. This library at least helps with it with ReconnectTimeout, so when no message comes from the server in this timeout range it tries to reconnect as fast as possible. And of course, you should send some kind of ping message every second to avoid multiple unnecessary reconnections.

Independently of that, there is also the feature keep-alive provided by websockets standard. It is exactly what I described but implemented on a protocol level. Unfortunately, not all servers support it, that's why I implemented a custom solution with ReconnectTimeout for that cases.

Marfusios avatar Aug 16 '21 15:08 Marfusios

thanks a lot for your answer. helped a lot.

dinos19 avatar Aug 19 '21 09:08 dinos19

KeepAlive is nothing related, so it's not going to affect it.

A problem with long-lived connections in general is that network equipment such as routers like to drop connections that appear to have “timed out”.

Fortunately, the WebSocket RFC includes a built-in ping/pong mechanism that can send periodic messages to keep the connection alive.

You can omit the option, since the default is to send a keep-alive message every 2 minutes.

_

This is happening due to how ReceiveAsync works behind the scenes. If you pass a CancellationToken to ReceiveAsync which lasts 5 seconds and then drop your connection on purpose, it's going to timeout in 5 seconds, not in 20 seconds (default), which is what you want, but there is an issue with that. The issue is that aborts the socket in 5 seconds if you don't receive a message from the remote server (WebSocketState = Aborted), which is bad because the remote server has to be sending messages in maximum 5 seconds, otherwise it aborts the socket. In other words, neither you or Marfurious can fix it. that's how it works on low level.

There are two types of closure:

  1. Graceful closure - Invoking CloseAsync/CloseOutputAsync changes the socket state to CloseSent which is then processed by ReceiveAsync: 1 byte, WebSocketMessageType.Close;
  2. When you interrupt it, meaning you've disconnected your Wi-Fi or your connection has suddenly dropped. It's going to try to receive a message (ReceiveAsync) for 20 seconds and it will then throw a WebSocketException with the following error code WebSocketError.ConnectionClosedPrematurely because the connection is no longer available.

ConnectAsync works in same way. It will throw WebSocketException in 20 seconds by default if it's unable to connect, but you put some timeout to it which is less than 20 seconds, it will throw TaskCanceledException instead.

Hulkstance avatar May 16 '22 08:05 Hulkstance