Does System.Net.WebSockets include a keepalive mechanism which automatically takes care of Ping/Pong control frames?
Yes, you read it right, sometimes you have those types of existential queries. :-)
This is actually a question that seems to be causing some confusion around the developers that are trying to use WebSockets.
In fact, if you look at the RFC of the WebSocket protocol (see below) you can see that it specifies exactly the case of the Ping-Pong mechanism. When a communication partner sends a Ping the client has to respond (as fast as possible) with a Pong message.
https://tools.ietf.org/html/rfc6455 (see section 5.5.2 and section 5.5.3), in there you can read:
“NOTE: A Ping frame may serve either as a keepalive or as a means to verify that the remote endpoint is still responsive.”
So, there should be no questions around this, right? ... Wrong.
This is really important, usually in the scenario where your client loses the network connection (and that will definitely happen from time to time) and for some security aspects (or any other aspect) you might need to get a notification pretty quick (lets say 3 seconds) when the client is no longer available.
From my experience, normally the developers follow the pah of setting the keepAliveInterval of the HttpListenerContext or sending “Dummy” messages every second, this of course will help on the server side to be informed when a client is no longer accessible.
However, most of times, when you have a running connection and you simply unplug the network cable at the client side it takes up to 30 seconds till the WebSocket.ReceiveAsync method fails. This is could be OK or could be unacceptable. Usually here resides the point of frustration of a lot of developer teams, this delay of 30 seconds to get the notification that the client is not there anymore.
So, basically we need to clarify the following :
Is there any way to force the Websocket-implementation to send a Websocket-Ping to the clients?
I will try to elaborate a little bit on this.
First, to be clear, System.Net.WebSockets includes indeed a keepalive mechanism which automatically takes care of Ping/Pong control frames.
These frames are the same as a regular frame but have a special opcode for ping and pong. To specify the interval, you need to specify the keepalive argument in the client and/or the server.
The client side is quite easy, by means of WebSocket.CreateClientWebSocket:
public static WebSocket CreateClientWebSocket(Stream innerStream, string subProtocol, int receiveBufferSize, int sendBufferSize, TimeSpan keepAliveInterval, bool useZeroMaskingKey, ArraySegment<byte> internalBuffer)
For the server side it’s a little different. You do it in the AcceptWebSocketAsync method of HttpListenerContext:
public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, TimeSpan keepAliveInterval)
When a ping is sent, a pong must be received or else the connection will be closed.
The default keepalive is set to 30 seconds, which would be the reason why most of the developers see the wait ~30 seconds before detecting something went wrong with the connection.
So, to address this delay, as referred above, you just need to specify the keepalive argument in the client and/or the server that fits your needs.
Hope that helps
Comments
- Anonymous
May 09, 2018
How about ASP.NET Core? There's no AcceptWebSocketAsync(string subProtocol, TimeSpan keepAliveInterval) overload.