4

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

4

2 回答 2

4

这只是一个想法。

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

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

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

于 2013-04-30T04:02:59.480 回答
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");
                    }
    }
    ...
 }
于 2013-04-30T08:42:45.087 回答