Skip to content
This repository has been archived by the owner on Feb 1, 2023. It is now read-only.

how to send data to all connected clients or selective clients? #29

Open
chhatraman08 opened this issue Nov 21, 2017 · 3 comments
Open

Comments

@chhatraman08
Copy link

No description provided.

@mika76
Copy link

mika76 commented Sep 18, 2018

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...

@oschwab
Copy link

oschwab commented Dec 18, 2018

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 ?

@swagfin
Copy link

swagfin commented Jan 12, 2023

@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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants