79310776

Date: 2024-12-27 02:30:57
Score: 0.5
Natty:
Report link

Web socket close handling

First, you have to approbriately handle the web socket close frame transfer which is a bit complex:

  1. You need 2 different cancellation tokens (one for the receive-listener-loop and one for your send-method/loop)

  2. In both, your close and receive methods, you need to catch OperationCanceledException but do nothing (as this is a normal exception when the connection is closed).

  3. In your receive-listener method, you need a Finally part on your try-catch-block where you cancel the send token and dispose and nullify your ClientWebSocket (as it is not re-usable after it has been closed).

  4. The server closes the connection:

4.1. You need to handle if the server sends a close frame within your receive-listener-loop. In there check for a received message with WebSocketMessageType.Close whereby state is changed from WebSocketState.Open to WebSocketState.CloseReceived.

4.2. Then, you cancel your send token and acknowledge the close frame received message back to the server whereby the state is changed to WebSocketState.Closed.

  1. The client (you) closes the connection:

5.1 In your own close method, you need to cancel the send token and then trigger clientWebSocket.CloseOutputAsync() with another timed cancellation token => state is changed from WebSocketState.Open to WebSocketState.CloseSent.

5.2. Immediately after this call, you need to wait until the server responded accordingly by which the state is changed to WebSocketState.Closed.

5.3. In the end of your close method, you cancel the listener token.

Here is a longer explanation of this logic and here is the corresponding code example.

Web socket interrupt handling

Additionally, you need to check if the connection is somehow interrupted. To do this, you catch WebSocketException in your receive method and check if the state is WebSocketState.Aborted. If so, then the connection to the web socket connection is lost (you can provoke and test this by enabling/disabling a corresponding firewall rule while your web socket is connected).

In order to be immediately informed about a connection loss, you need to enable the KeepAlive options (Interval & Timeout) of your ClientWebSocket, e.g.:

clientWebSocket.Options.KeepAliveInterval = TimeSpan.FromSeconds(1);
clientWebSocket.Options.KeepAliveTimeout = TimeSpan.FromSeconds(5);

Otherwise, you will only get informed when you try to send something.

General OnClientWebSocketStateChanged handling

Unfortunately, ClientWebSocket is a sealed class whereby you are not able to directly add some internal event handler. Therefore, to immediately get informed whenever the state of your ClientWebSocket changes, you would need to add an own external WebSocketState field and a small method to compare this field against your clientWebSocket.State. If it is different, update the field and use some inform mechanism (e.g. trigger an own event to which you forward the updated state to).

Finally, you need to call this method multiple times in your connect, close and receive-message loop methods whenever the state could change (I needed to call it 5 times in each method but it depends on your implementation).

Reasons:
  • Blacklisted phrase (0.5): I need
  • Contains signature (1):
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (0.5):
Posted by: tar