feat: Simple implementation of heartbeats
This commit is contained in:
parent
3d6dbc5aa5
commit
a15c0c2a87
@ -16,12 +16,15 @@ namespace ArStomp
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class StompClient
|
public class StompClient
|
||||||
{
|
{
|
||||||
|
private int heartBeatInMillis;
|
||||||
public static bool Debug { get; set; } = false;
|
public static bool Debug { get; set; } = false;
|
||||||
private WebSocket ws;
|
private WebSocket ws;
|
||||||
private volatile bool stompConnected = false;
|
private volatile bool stompConnected = false;
|
||||||
public CancellationTokenSource Token { get; } = new CancellationTokenSource();
|
public CancellationTokenSource Token { get; } = new CancellationTokenSource();
|
||||||
private readonly X509Certificate2Collection certCollection;
|
private readonly X509Certificate2Collection certCollection;
|
||||||
private readonly Dictionary<string, Subscription> subs = new Dictionary<string, Subscription>();
|
private readonly Dictionary<string, Subscription> subs = new Dictionary<string, Subscription>();
|
||||||
|
private DateTime lastSend = DateTime.UtcNow;
|
||||||
|
private DateTime lastRcvd = DateTime.UtcNow;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handler of incoming messages.
|
/// Handler of incoming messages.
|
||||||
/// Used only for RPC. <see cref="Subscription">Subsscriptions</see> have own handlers.
|
/// Used only for RPC. <see cref="Subscription">Subsscriptions</see> have own handlers.
|
||||||
@ -33,14 +36,12 @@ namespace ArStomp
|
|||||||
/// Works with binary frames.
|
/// Works with binary frames.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="certCollection">collection of root ca certificates (if TLS is used)</param>
|
/// <param name="certCollection">collection of root ca certificates (if TLS is used)</param>
|
||||||
public StompClient(X509Certificate2Collection certCollection = null)
|
public StompClient(X509Certificate2Collection certCollection = null, int heartBeatSec = 20)
|
||||||
{
|
{
|
||||||
|
this.heartBeatInMillis = heartBeatSec * 1000;
|
||||||
if (certCollection != null && certCollection.Count > 0)
|
if (certCollection != null && certCollection.Count > 0)
|
||||||
{
|
{
|
||||||
this.certCollection = certCollection;
|
this.certCollection = certCollection;
|
||||||
|
|
||||||
// In .netstandard2.0 - setup validator globally
|
|
||||||
// System.Net.ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidationCallback;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,12 +173,14 @@ namespace ArStomp
|
|||||||
ws.OnOpen += (sender, o) =>
|
ws.OnOpen += (sender, o) =>
|
||||||
{
|
{
|
||||||
if (Debug) System.Console.WriteLine("OnOpen");
|
if (Debug) System.Console.WriteLine("OnOpen");
|
||||||
StompFrm connect = new StompFrm(login, password);
|
StompFrm connect = new StompFrm(login, password, heartBeatInMillis);
|
||||||
|
lastSend = DateTime.UtcNow;
|
||||||
Task.Run(() => { return connect.Serialize(ws, ct); });
|
Task.Run(() => { return connect.Serialize(ws, ct); });
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.OnMessage += (sender, o) =>
|
ws.OnMessage += (sender, o) =>
|
||||||
{
|
{
|
||||||
|
lastRcvd = DateTime.UtcNow;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Debug)
|
if (Debug)
|
||||||
@ -195,7 +198,8 @@ namespace ArStomp
|
|||||||
ExpectFrame(fr, FrameType.Connected);
|
ExpectFrame(fr, FrameType.Connected);
|
||||||
openTask.TrySetResult(true);
|
openTask.TrySetResult(true);
|
||||||
if (Debug) System.Console.WriteLine("Logon done");
|
if (Debug) System.Console.WriteLine("Logon done");
|
||||||
} catch (Exception e)
|
}
|
||||||
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
openTask.TrySetException(e);
|
openTask.TrySetException(e);
|
||||||
}
|
}
|
||||||
@ -224,7 +228,7 @@ namespace ArStomp
|
|||||||
/// <returns>true if it looks like we have proper connection to server</returns>
|
/// <returns>true if it looks like we have proper connection to server</returns>
|
||||||
public bool IsConnected()
|
public bool IsConnected()
|
||||||
{
|
{
|
||||||
return ws != null && ws.IsAlive;
|
return ws != null && ws.IsAlive && (DateTime.UtcNow - lastRcvd) < TimeSpan.FromMilliseconds(3 * heartBeatInMillis);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send message
|
/// Send message
|
||||||
@ -238,6 +242,7 @@ namespace ArStomp
|
|||||||
|
|
||||||
SendFrm send = new SendFrm(destination, correlationId, body);
|
SendFrm send = new SendFrm(destination, correlationId, body);
|
||||||
await send.Serialize(ws, ct);
|
await send.Serialize(ws, ct);
|
||||||
|
lastSend = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int SubId = 0;
|
private int SubId = 0;
|
||||||
@ -308,6 +313,12 @@ namespace ArStomp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (fr.Type == FrameType.Heartbeat || DateTime.UtcNow - lastSend > TimeSpan.FromSeconds(20))
|
||||||
|
{
|
||||||
|
lastSend = DateTime.UtcNow;
|
||||||
|
ws.Send(new byte[] { 10 }); // send heartbeat
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -103,18 +103,18 @@ namespace ArStomp
|
|||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
ws.Send(stream, (int) stream.Length);
|
ws.Send(stream, (int) stream.Length);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
//return ws.SendAsync(new ArraySegment<byte>(array, 0, (int)stream.Position), WebSocketMessageType.Binary, true, cancellationToken);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class StompFrm : Frame
|
internal class StompFrm : Frame
|
||||||
{
|
{
|
||||||
public StompFrm(string login, string passwd)
|
public StompFrm(string login, string passwd, int hbmilis)
|
||||||
{
|
{
|
||||||
Type = FrameType.Stomp;
|
Type = FrameType.Stomp;
|
||||||
Headers["login"] = login;
|
Headers["login"] = login;
|
||||||
Headers["passcode"] = passwd;
|
Headers["passcode"] = passwd;
|
||||||
Headers["accept-version"] = "1.2";
|
Headers["accept-version"] = "1.2";
|
||||||
|
if (hbmilis > 0) Headers["heart-beat"] = $"{hbmilis},{hbmilis}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user