会话管理
会话管理用来管理用户的标识,它与 ConnectionId 进行映射,可双向查找。SessionManager
是一个泛型类,它接收一个任意的类型作为用户标识,该用户标识类需要重写 ToString 方法,以输出用户标识字符串,作为检索依据。
下面建立一个自定义的用户标识类,包含用户ID、用户类型和用户名称,其标识使用 Type:Id 字符串,如下所示:
public class User
{
public int Id { get; set; }
public int Type { get; set; }
public string Name { get; set; }
public override string ToString()
{
return $"{Type}:{Id}";
}
}
在 WebSocketHandler
实现类中,实现如下代码:
public class ChatHandler : WebSocketHandler
{
private SessionManager<User> _manager = new SessionManager<User>();
/// <summary>
/// 客户端连接上后,使用该方法添加用户标识。
/// </summary>
/// <param name="userId"></param>
/// <param name="userType"></param>
/// <param name="userName"></param>
public void Connect(int userId, int userType, string userName)
{
_manager.Add(ConnectionId, new User { Id = userId, Type = userType, Name = userName });
}
/// <summary>
/// 向用户发送消息。
/// </summary>
/// <param name="userId"></param>
/// <param name="userType"></param>
/// <param name="message"></param>
public void Send(int userId, int userType, string message)
{
//根据标识查找 connectioId,然后向其发送通知
var connectioId = _manager.FindConnection(new User { Id = userId, Type = userType });
if (!string.IsNullOrEmpty(connectioId))
{
Clients.Client(connectioId).SendAsync("OnReceiveMsg", message);
}
}
protected override void OnDisconnected()
{
_manager.Remove(ConnectionId);
base.OnDisconnected();
}
protected override void OnHeartBeating()
{
//心跳时刷新用户会话
_sessionManager.Refresh(ConnectionId);
base.OnHeartBeating();
}
}
FindIdentity 方法可以通过 ConnectionId 查找对应的用户标识,如下所示:
public class ChatHandler : WebSocketHandler
{
private SessionManager<User> _manager = new SessionManager<User>();
protected override void OnDisconnected()
{
var user = _sessionManager.FindIdentity(ConnectionId);
_sessionManager.Remove(ConnectionId);
//某人下线后,通知所有人,并更新在线人数
Clients.All.SendAsync("onNotifyOffline", user.Name, _sessionManager.Count);
base.OnDisconnected();
}
}
GetIdentityTable 方法用于获取 ConnectionId 与用户标识的映射字典,GetIdentityList 方法用于获取用户标识列表,如下所示:
public class ChatHandler : WebSocketHandler
{
private SessionManager<User> _manager = new SessionManager<User>();
/// <summary>
/// 客户端连接上后,使用该方法添加用户标识。
/// </summary>
/// <param name="userId"></param>
/// <param name="userType"></param>
/// <param name="userName"></param>
public void Connect(int userId, int userType, string userName)
{
_manager.Add(ConnectionId, new User { Id = userId, Type = userType, Name = userName });
var users = _sessionManager.GetIdentityList().OrderBy(s => s.Name).ToList();
//通知所有人,刷新在线列表
Clients.All.SendAsync("onUpdateOnlineList", users);
//通知其他人,某人上线了
Clients.Other.SendAsync("onNotifyOnline", userName);
}
}
💡 小提示
使用分布式部署后,会话管理器会使用分布式缓存管理器,因此你需要配置 Reids 之类的分布式缓存管理器。