【问题标题】:Tracking SignalR connection ids to see if they really exist跟踪 SignalR 连接 ID 以查看它们是否真的存在
【发布时间】:2013-04-30 16:42:45
【问题描述】:

目前,我通过将所有已连接用户的连接 ID 映射到实际的应用程序用户,将它们存储在我的数据库中。我在这里所做的非常简单:当OnConnected 事件被触发时,我将连接ID​​ 添加到数据库中。然后,当OnDisconnected 事件被触发时,我从数据库中删除该连接。

但是,在某些情况下(例如,当进程终止时等),我没有收到断开连接事件。这使我的连接表不可靠,因为我无法确定用户是否连接在一个或多个客户端上。例如,下面是我的OnDisconnected 方法中的一段代码:

HubConnection hubConnection = _hubConnectionRepository.GetAll()
    .FirstOrDefault(conn => conn.ConnectionId == connectionId);

if (hubConnection != null)
{
    _hubConnectionRepository.Delete(hubConnection);
    _hubConnectionRepository.Save();
}

if (!_hubConnectionRepository.GetAll().Any(conn => conn.UserId == user.Id))
{
    Clients.Others.userDisconnected(username);
}

如您所见,在我删除他/她的当前连接后,我会检查是否有与该用户关联的任何其他连接。根据情况,我会向所有连接的客户端广播一条消息。

我想要的是这样的:能够使用一组连接 ID 轮询 SignalR 系统并取回断开连接的 ID,以便我可以将它们从数据库内的连接列表中删除。据我从与 David Fowler 的谈话中记得,这在今天是不可能的,但在这种情况下,首选的方法是什么?

【问题讨论】:

    标签: asp.net real-time signalr signalr-hub


    【解决方案1】:

    这只是一个想法。

    在服务器上: Clients.All.ping()

    在客户端: hub.client.ping = function() { hub.server.pingResponse(); }

    在服务器上: 无效 pingResponse() { Context.ConnectionId; //更新数据库 }

    【讨论】:

    • 嗨,我刚开始使用 SignalR,想做一些涉及跟踪的事情。我喜欢你对这个的想法。想知道 2 年后这是否仍然是正确的方法,或者是否有类似的解决方案可能更多地成为今天的解决方案。有人吗?
    【解决方案2】:

    这就是我所做的:

    我有一个类HubConnectionManager

    public class HubConnectionManager
    {
        static HubConnectionManager()
        {
            connections = new Dictionary<string, List<string>>();
            users = new List<Login>();
        }
    
        #region Static Fields
    
        private static Dictionary<string, List<string>> connections;
    
        private static List<Login> users; 
    
        #endregion
    
        #region Public Properties
    
        public static Dictionary<string, List<string>> Connections
        {
            get
            {
                return connections;
            }
        }
    
        #endregion
    
        #region Public Methods and Operators
    
        public static void AddConnection(Login login, string connectionId)
        {
            if (!connections.ContainsKey(login.LoginName))
            {
                connections.Add(login.LoginName, new List<string>());
    
                if (!users.Contains(login))
                {
                    users.Add(login);
                }
            }
    
            // add with new connection id
            connections[login.LoginName].Add(connectionId);
        }
    
        public static bool IsOnline(string connectionId)
        {
            return connections.Any(x => !string.IsNullOrEmpty(x.Value.FirstOrDefault(y => y == connectionId)));
        }
    
        public static void RemoveConnection(string user, string connectionId)
        {
            if (connections.ContainsKey(user))
            {
                connections[user].Remove(connectionId);
    
                if (connections[user].Count == 0)
                {
                    connections.Remove(user);
    
                    // remove user
                    users.RemoveAll(x => x.LoginName == user);
                }
            }
        }
    
        public static int GetAllConnectionsCount()
        {
            return connections.Keys.Sum(user => connections[user].Count);
        }
    
        public static Login GetUser(string connectionId)
        {
            string userName = connections.FirstOrDefault(x => x.Value.Any(y => y == connectionId)).Key;
            return users.FirstOrDefault(x => x.LoginName == userName);
        }
    
        #endregion
    }
    

    我正在使用包含 UserName 及其连接列表的字典(这是因为就像您所说的,有时 OnDisconnected 无法正常触发:

    connections = new Dictionary<string, List<string>>();
    

    然后在您的集线器中,您可以检查连接是否仍然“已连接”/有效:

    public class TaskActionStatus : Hub
    {
        public void SendMessage()
        {
                        if (HubConnectionManager.IsOnline(Context.ConnectionId))
                        {
                            this.Clients.Client(Context.ConnectionId).actionInit("test");
                        }
        }
        ...
     }
    

    【讨论】:

    • 这没什么错,只是它应该是线程安全的!
    • 很好的解决方案,但是如果您的服务器已关闭并且您将 connectionId 保存在 db/outer 缓存中并且客户端已关闭,您将在列表中获得“永恒”连接:(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-06
    • 2022-11-12
    • 2020-10-30
    • 1970-01-01
    • 1970-01-01
    • 2017-12-05
    相关资源
    最近更新 更多