I'm trying to figure out how to send ping
/pong
heartbeats in order to be sure to maintain a connection with a Websocket server using Websocket .NET client in a .NET Core WPF Application, so I'm testing with this Binance Websocket which says
The websocket server will send a
ping frame
every 3 minutes. If the websocket server does not receive apong frame
back from the connection within a 10 minute period, the connection will be disconnected. Unsolicitedpong frames
are allowed.
However, when I try to connect using my sample code, I simply never receive any message from the websocket that contains the string ping
, and the connection seems to never fail if there is at least one stream subscribed to. Also sending unsolicited pong
messages seems to always throw an error 3: invalid JSON
followed by a disconnection.
Are ping
/pong
heartbeats managed by the NuGet Package (even though I didn't find any line that mentions ping
or pong
in its source code), or simply doesn't support them? If so then how/why is my connection to Binance Websocket not getting disconnected?
Here's my sample code for the WSClient
class so you can try and see that you won't get disconnected even after +15mins:
Update: It's handled internally by the WebsocketClient
, and the KeepAliveInterval
is actually sending pong
frames each interval. I wonder though if it's possible to subscribe some event to see when these frames are being sent, which could be useful when dealing with strict messages rates limitations to not get accidently disconnected when sending the max number of messages at the same time as the pong frame is being sent.
using System;
using System.Net.WebSockets;
using Websocket.Client;
using Websocket.Client.Models;
using System.Threading.Tasks;
using System.Reactive.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
public class WSClient
{
private List<string> logs = new List<string>();
private WebsocketClient client;
private string wsUrl = "wss://stream.binance.com/ws";
public WSClient() { }
public async Task InitializeClient()
{
Uri uri = new Uri(wsUrl);
Func<ClientWebSocket> factory = new Func<ClientWebSocket>(() => {
ClientWebSocket wsClient = new ClientWebSocket
{
Options =
{
KeepAliveInterval = TimeSpan.FromSeconds(5) // interval to send pong frames }
};
return wsClient;
});
client = new WebsocketClient(uri, factory);
client.Name = "WebsocketClient";
client.ReconnectTimeout = TimeSpan.FromSeconds(30);
client.ErrorReconnectTimeout = TimeSpan.FromSeconds(30);
client.ReconnectionHappened.Subscribe(OnReconnection);
client.DisconnectionHappened.Subscribe(OnDisconnect);
client.MessageReceived
.Where((ResponseMessage message) => message.MessageType == WebSocketMessageType.Text)
.Subscribe(OnMessage);
try
{
await client.StartOrFail();
}
catch (Exception ex)
{
logs.Add($"Error: { ex.Message }");
}
// Subscribing to a stream (btcusdt@aggTrade for example)
client.Send("{\"method\": \"SUBSCRIBE\",\"params\":[\"btcusdt@aggTrade\"],\"id\": 1}");
}
private void OnReconnection(ReconnectionInfo info)
{
logs.Add("Reconnected");
}
private void OnMessage(ResponseMessage message)
{
logs.Add(message.Text);
}
private void OnDisconnect(DisconnectionInfo info)
{
logs.Add("Diconnected");
}
}
Websocket
protocol, butTLSv1.2
instead. I couldn't read any meaning information besides that.TLSv1.2
packets. These servers however do not require to sendping
/pong
raw frames which is necessary for the first one.