2013-04-29 1 views
4

현재 연결된 모든 사용자의 연결 ID를 실제 응용 프로그램 사용자에게 매핑하여 데이터베이스에 저장합니다. 내가 여기서하는 일은 꽤 간단하다 : OnConnected 이벤트가 발생하면 데이터베이스에 연결 ID를 추가한다. 그런 다음 OnDisconnected 이벤트가 발생하면 데이터베이스에서 해당 연결을 제거합니다.SignalR 연결 ID를 추적하여 실제 존재 여부 확인

그러나 일부 경우 (예 : 프로세스가 종료 될 때 등) 연결 해제 이벤트가 발생하지 않습니다. 이것은 사용자가 하나 이상의 클라이언트에 연결되어 있는지 확신 할 수 없기 때문에 연결 테이블을 신뢰할 수 없게 만듭니다. 보시다시피

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); 
} 

, 나는 내가 그/그녀의 현재 연결을 제거 직후 해당 사용자에게 관련된 다른 연결이 있는지 확인 : 예를 들어, 여기 내 OnDisconnected 방법에 코드 블록이다. 케이스에 따라 연결된 모든 클라이언트에게 메시지를 브로드 캐스트합니다.

내가 원하는 것은 연결 식별자 배열을 사용하여 SignalR 시스템을 폴링하고 연결 해제 된 연결을 다시 가져와 데이터베이스 내의 연결 목록에서 제거 할 수 있도록하는 것입니다. David Fowler와의 대화에서 기억하는 한, 오늘은 불가능하지만 그런 경우에 대해 바람직한 접근 방법은 무엇입니까?

답변

4

이것은 하나의 아이디어 일뿐입니다.

서버에서

: Clients.All.ping()

클라이언트에서

: hub.client.ping = 함수() { hub.server.pingResponse(); } 서버에서

: 공극 pingResponse() { Context.ConnectionId; 나는 사용자 이름을 보유하고 사전을 사용하고

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 
} 

과는 연결 목록 (의 :

I 클래스 HubConnectionManager이 : // 업데이트 데이터베이스 은}

+0

안녕하세요, 저는 SignalR을 사용하기 시작했으며 추적이 필요한 작업을 수행하려고합니다. 나는 이것에 대한 당신의 생각을 좋아합니다. 2 년이 지난 후에도 여전히 올바른 방법인지 아니면 솔루션으로 오늘보다 더 많은 유사 솔루션이 있는지 궁금합니다. 누군가? –

2

이것은 내가 무슨 짓을 당신이 말했듯이 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

좋은 해결책이지만, 서버가 다운 된 상태에서 db/outer 캐시에 connectionId를 저장하고 클라이언트가 꺼져 있다면 목록에 "영원한"연결이 생깁니다. – Nigrimmist