跟踪SignalR连接ID以查看它们是否真的存在

时间:2013-04-29 13:58:32

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

目前,我将所有连接用户的连接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,以便我可以从数据库内的连接列表中删除它们。据我在与大卫福勒的谈话中记得,今天这是不可能的,但这种情况下首选的方法是什么?

2 个答案:

答案 0 :(得分:4)

这只是一个想法。

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

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

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

答案 1 :(得分: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");
                    }
    }
    ...
 }