2013-04-29 2 views
4

В настоящее время я храню все подключенные идентификаторы подключений пользователя в моей базе данных, сопоставляя их с фактическими пользователями приложений. Что мне делать, здесь довольно просто: я добавляю идентификатор соединения в базу данных при запуске события OnConnected. Затем я удаляю это соединение из базы данных при запуске события OnDisconnected.Отслеживание идентификаторов соединения SignalR, чтобы узнать, действительно ли они существуют

Однако в некоторых случаях (например, когда процесс завершается и т. Д.), Я не получаю событие разъединения. Это делает мою таблицу соединений ненадежной, потому что я не могу быть уверен, что пользователь подключен к одному или нескольким клиентам. Например, здесь есть блок кода на моем 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); 
} 

Как вы видите, я проверить, есть ли какие-либо другие соединения, связанные с этим пользователем только после того, как я удалить его/ее текущее соединение. В зависимости от случая я передаю сообщение всем подключенным клиентам.

Что я хочу здесь, это что-то вроде этого: чтобы иметь возможность опросить систему SignalR с массивом идентификаторов подключения и вернуть отключенные, чтобы я мог удалить их из своего списка соединений внутри базы данных. Насколько я помню из моего разговора с Дэвидом Фаулером, сегодня это невозможно, но какой предпочтительный подход к таким случаям?

ответ

4

Это всего лишь идея.

На сервере: Clients.All.ping()

На клиентов: hub.client.ping = функция() { hub.server.pingResponse(); }

На сервере: недействительный pingResponse() { Context.ConnectionId; // обновление базы }

+0

Привет, Я только начинаю использовать 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>>(); 

n в вашем концентраторе, вы можете проверить, все ли соединение «подключено»/действительно:

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

Ничего страшного в этом, кроме того, что он должен быть потокобезопасным! –

+0

Хорошее решение, но если ваш сервер был выключен, и вы сохранили connectionId в db/external cache и клиент был выключен, вы получите «вечное» соединение в своем списке :( – Nigrimmist

 Смежные вопросы

  • Нет связанных вопросов^_^