How to keep track of established connections using WebSockets

后端 未结 2 481
旧巷少年郎
旧巷少年郎 2021-01-13 03:40

I am trying to get a real-time chat service for cross-platform devices to life. The problem is that System.Net.WebSockets namespace doesn\'t allow me directly

2条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-01-13 04:01

    Usually, you do not do something like that. The WebSocket should be just and endpoint to another layer or sub-system. For example, an event-driven architecture. On connection, you should start the handler, gather data from the connected socket like the cookie, the URL or whatever, and notify something else that such user with that cookie/url is connected in that socket.

    About your code:

    • Do not declare the read buffer inside the loop, you can reuse it.
    • WebSockets always send text data as UTF8, not ASCII.

    This would be a way of keep track of your users in a small project, but I recommend you to plug the WebSocket to another message infrastructure like MassTransit:

    public class WSHandler : IHttpHandler
    {
        public bool IsReusable { get { return false; } }
    
        public void ProcessRequest(HttpContext context)
        {
            if (context.IsWebSocketRequest)
            {
                context.AcceptWebSocketRequest(ProcessWSChat);
            }
        }
    
        static readonly ConcurrentDictionary _users = new ConcurrentDictionary();
    
        private async Task ProcessWSChat(AspNetWebSocketContext context)
        {
            WebSocket socket = context.WebSocket;
            ArraySegment buffer = new ArraySegment(new byte[4096]);
    
            //Identify user by cookie or whatever and create a user Object
            var cookie = context.Cookies["mycookie"];
            var url = context.RequestUri;
    
            IPrincipal myUser = GetUser(cookie, url);
    
            // Or uses the user that came from the ASP.NET authentication.
            myUser = context.User;
    
            _users.AddOrUpdate(myUser, socket, (p, w) => socket);
    
            while (socket.State == WebSocketState.Open)
            {
                WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None)
                                                            .ConfigureAwait(false);
                String userMessage = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);
    
                userMessage = "You sent: " + userMessage + " at " +
                    DateTime.Now.ToLongTimeString() + " from ip " + context.UserHostAddress.ToString();
                var sendbuffer = new ArraySegment(Encoding.UTF8.GetBytes(userMessage));
    
                await socket.SendAsync(sendbuffer , WebSocketMessageType.Text, true, CancellationToken.None)
                            .ConfigureAwait(false);
            }
    
            // when the connection ends, try to remove the user
            WebSocket ows;
            if (_users.TryRemove(myUser, out ows))
            {
                if (ows != socket)
                {
                    // whops! user reconnected too fast and you are removing
                    // the new connection, put it back
                    _users.AddOrUpdate(myUser, ows, (p, w) => ows);
                }
            }
        }
    
        private IPrincipal GetUser(HttpCookie cookie, Uri url)
        {
            throw new NotImplementedException();
        }
    }
    

提交回复
热议问题