You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/fundamentals/networking/websockets.md
+73Lines changed: 73 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -99,3 +99,76 @@ using ClientWebSocket ws = new()
99
99
100
100
> [!IMPORTANT]
101
101
> Before using compression, please be aware that enabling it makes the application subject to CRIME/BREACH type of attacks, for more information, see [CRIME](https://en.wikipedia.org/wiki/CRIME) and [BREACH](https://en.wikipedia.org/wiki/BREACH). It is strongly advised to turn off compression when sending data containing secrets by specifying the `DisableCompression` flag for such messages.
102
+
103
+
## Keep-Alive strategies
104
+
105
+
On **.NET 8** and earlier, the only available Keep-Alive strategy is _Unsolicited PONG_. This strategy is enough to keep the underlying TCP connection from idling out. However, in a case when a remote host becomes unresponsive (for example, a remote server crashes), the only way to detect such situations with Unsolicited PONG is to depend on the TCP timeout.
106
+
107
+
**.NET 9** introduced the long-desired _PING/PONG_ Keep-Alive strategy, complementing the existing `KeepAliveInterval` setting with the new `KeepAliveTimeout` setting. Starting with .NET 9, the Keep-Alive strategy is selected as follows:
108
+
109
+
1. Keep-Alive is **OFF**, if
110
+
-`KeepAliveInterval` is `TimeSpan.Zero` or `Timeout.InfiniteTimeSpan`
111
+
2.**Unsolicited PONG**, if
112
+
-`KeepAliveInterval` is a positive finite `TimeSpan`, -AND-
113
+
-`KeepAliveTimeout` is `TimeSpan.Zero` or `Timeout.InfiniteTimeSpan`
114
+
3.**PING/PONG**, if
115
+
-`KeepAliveInterval` is a positive finite `TimeSpan`, -AND-
116
+
-`KeepAliveTimeout` is a positive finite `TimeSpan`
117
+
118
+
The default `KeepAliveTimeout` value is `Timeout.InfiniteTimeSpan`, so the default Keep-Alive behavior remains consistent between .NET versions.
119
+
120
+
If you use `ClientWebSocket`, the default <xref:System.Net.WebSockets.ClientWebSocketOptions.KeepAliveInterval?displayProperty=nameWithType> value is <xref:System.Net.WebSockets.WebSocket.DefaultKeepAliveInterval?displayProperty=nameWithType> (typically 30 seconds). That means, `ClientWebSocket` has the Keep-Alive ON by default, with Unsolicited PONG as the default strategy.
121
+
122
+
If you want to switch to the PING/PONG strategy, overriding <xref:System.Net.WebSockets.ClientWebSocketOptions.KeepAliveTimeout?displayProperty=nameWithType> is enough:
For a basic `WebSocket`, the Keep-Alive is OFF by default. If you want to use the PING/PONG strategy, both <xref:System.Net.WebSockets.WebSocketCreationOptions.KeepAliveInterval?displayProperty=nameWithType> and <xref:System.Net.WebSockets.WebSocketCreationOptions.KeepAliveTimeout?displayProperty=nameWithType> need to be set:
If the Unsolicited PONG strategy is used, PONG frames are used as a unidirectional heartbeat. They sent regularly with `KeepAliveInterval` intervals, regardless whether the remote endpoint is communicating or not.
142
+
143
+
In case the PING/PONG strategy is active, a PING frame is sent after `KeepAliveInterval` time passed since the _last communication_ from the remote endpoint. Each PING frame contains an integer token to pair with the expected PONG response. If no PONG response arrived after `KeepAliveTimeout` elapsed, the remote endpoint is deemed unresponsive, and the WebSocket connection is automatically aborted.
If the timeout elapses, an outstanding `ReceiveAsync` throws an `OperationCanceledException`:
157
+
158
+
```txt
159
+
System.OperationCanceledException: Aborted
160
+
---> System.AggregateException: One or more errors occurred. (The WebSocket didn't receive a Pong frame in response to a Ping frame within the configured KeepAliveTimeout.) (Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request..)
161
+
---> System.Net.WebSockets.WebSocketException (0x80004005): The WebSocket didn't receive a Pong frame in response to a Ping frame within the configured KeepAliveTimeout.
162
+
at System.Net.WebSockets.ManagedWebSocket.KeepAlivePingHeartBeat()
163
+
...
164
+
```
165
+
166
+
### Keep Reading To Process PONGs
167
+
168
+
> [!NOTE]
169
+
> Currently, `WebSocket` ONLY processes incoming frames while there's a `ReceiveAsync` pending.
170
+
171
+
> [!IMPORTANT]
172
+
> If you want to use Keep-Alive Timeout, it's _crucial_ that PONG responses are _promptly processed_. Even if the remote endpoint is alive and properly sends the PONG response, but the `WebSocket` isn't processing the incoming frames, the Keep-Alive mechanism can issue a "false-positive" Abort. This problem can happen if the PONG frame is never picked up from the transport stream before the timeout elapsed.
173
+
174
+
To avoid tearing up good connections, users are advised to maintain a pending read on all WebSockets that have Keep-Alive Timeout configured.
0 commit comments