2013-04-29 62 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