目前,我将所有连接用户的连接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,以便我可以从数据库内的连接列表中删除它们。据我在与大卫福勒的谈话中记得,今天这是不可能的,但这种情况下首选的方法是什么?
答案 0 :(得分:4)
这只是一个想法。
在服务器上: Clients.All.ping()
对客户: hub.client.ping = function(){ hub.server.pingResponse(); }
在服务器上: void pingResponse() { Context.ConnectionId; //更新数据库 }
答案 1 :(得分: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");
}
}
...
}