2013-04-29 46 views
4

目前,我将所有连接的用户连接ID存储在数据库中,方法是将它们映射到实际的应用程序用户。我在这里做的很简单:当OnConnected事件被触发时,我将连接ID​​添加到数据库中。然后,我会在触发OnDisconnected事件时从数据库中删除该连接。跟踪SignalR连接ID以查看它们是否真的存在

但是,在某些情况下(例如,当进程终止等)时,我不会收到断开连接事件。这使得我的连接表不可靠,因为我无法确定用户是否连接到一个或多个客户端。例如,这里是代码我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系统并取回断开连接的数据,以便我可以从数据库中的连接列表中删除它们。据我与David Fowler的谈话记得,今天这是不可能的,但在这种情况下,首选方法是什么?

回答

4

这只是一个想法。

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

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

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

+0

嗨,我刚开始使用SignalR并希望做一些涉及跟踪。我喜欢你的想法。想知道如果在2年之后,这仍然是正确的方式,或者如果现在有更多类似的解决方案可以作为解决方案。任何人? – 2015-12-10 19:13:18

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 
} 

我使用保持着用户名字典,它是连接列表(这是因为像你说的有时OnDisconnected不能正常着火:

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

n在你的集线器,你可以检查一个连接是否仍然“连接”/有效:

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

没有错,除了它应该是线程安全的! – 2013-12-12 12:18:40

+0

好的解决方案,但是如果你的服务器关闭了,并且你保存了db/outer cache中的connectionId并且客户端关闭了,你将在你的列表中获得“永恒”连接:( – Nigrimmist 2016-04-08 22:08:54