how to send data to all connected clients or selective clients?
This is my solution to the problem...
[WebSocketRoute("/ws")]
public class MyWebSocket : WebSocketConnection
{
private static Dictionary<Guid,MyWebSocket> connections = new Dictionary<Guid, MyWebSocket>();
public Guid UniqueId { get; }
public MyWebSocket()
{
UniqueId = Guid.NewGuid();
}
public override void OnOpen()
{
connections.Add(UniqueId, this);
System.Diagnostics.Debug.WriteLine("New websocket connected {0}, now have {1} in list", UniqueId, connections.Count);
}
public override void OnClose(WebSocketCloseStatus? closeStatus, string closeStatusDescription)
{
Close(WebSocketCloseStatus.NormalClosure, "");
connections.Remove(UniqueId);
System.Diagnostics.Debug.WriteLine("Websocket {0} closed, now have {1} in list", UniqueId, connections.Count);
}
public override void OnReceiveError(Exception error)
{
Close(WebSocketCloseStatus.ProtocolError, error.Message);
connections.Remove(UniqueId);
System.Diagnostics.Debug.WriteLine("Websocket {0} errored with {1}, now have {2} in list", UniqueId, error.Message, connections.Count);
}
public override async Task OnMessageReceived(ArraySegment<byte> message, WebSocketMessageType type)
{
if (type == WebSocketMessageType.Text)
{
var txt = System.Text.Encoding.UTF8.GetString(message.Array, message.Offset, message.Count);
var output = System.Text.Encoding.UTF8.GetBytes("Received: " + txt);
await SendText(output, true);
}
}
public static void Broadcast(string text, params object[] args)
{
var txtBuffer = System.Text.Encoding.UTF8.GetBytes(string.Format(text, args));
foreach(var conn in connections.Values)
{
conn.SendText(txtBuffer, true);
}
}
}
so having that static method I can call MyWebSocket.Broadcast("some event {0}", "0101"); from anywhere...
Hello,
When using this code (Framework 4.7.2) , my websocket client says that it is disconnected by the server just after open.
The problem seems to come from connections.Add(UniqueId, this); . Any idea why ?
@mika76 you have to put this code on a background thread and not within the MyWebSocket class `public static class NotificationDispatcher { private static ConcurrentQueue<byte[]> ActiveQueue { get; set; } = new ConcurrentQueue<byte[]>();
private static Thread RunningThread;
private static Dictionary<Guid, NotificationsRoute> _clients = new Dictionary<Guid, NotificationsRoute>();
public static void ClientAdd(NotificationsRoute route) => _clients.Add(route.UniqueId, route);
public static void ClientRemove(Guid guid) => _clients.Remove(guid);
public static void QueueMessage(byte[] message) => ActiveQueue.Enqueue(message);
public static void StartDispatch(CancellationToken cancellationToken)
{
ActiveQueue = new ConcurrentQueue<byte[]>();
RunningThread = new Thread(() =>
{
DateTime lastHeartbeat = DateTime.Now.AddDays(-1);
while (!cancellationToken.IsCancellationRequested)
{
try
{
if (ActiveQueue.TryDequeue(out byte[] dispatchMessage) && dispatchMessage.Length > 0)
foreach (var conn in _clients.Values)
{
_ = conn.SendText(dispatchMessage, true);
}
}
catch (Exception ex)
{
Logger.Log("[Dispatcher Thread Error]" + ex.ToString(), LogLevel.Error);
}
//Sample
if (lastHeartbeat < DateTime.Now.AddSeconds(-10))
{
ActiveQueue.Enqueue($"Heartbeat here at: {lastHeartbeat:yyyy-MM-dd HH:mm:ss}".JsonEncodeSocketMessage());
lastHeartbeat = DateTime.Now;
}
Thread.Sleep(1000);
}
});
RunningThread.Start();
}
public static void StopDispatch()
{
try { RunningThread?.Abort(); _clients = null; } catch { }
}
}`
I am sending a Heartbeat message to all connected clients to see if all clients are getting the message and works great