ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(八) 之 用 Redis 实现用户在线离线状态消息处理
前言
上篇的预告好像是“聊天室的小细节,你都注意到了吗?”。今天也是为那篇做铺垫吧。之前的版本有好多问题,比如:当前登录用户是否合法问题,userid参数如果随便传后台没有验证。还有一个致命的问题,用户AB都在线,但是如果A没有打开B的窗口或者B没有打开A的窗口,那么发消息,对方是收不到的。因为他们没有进入到同一个组里面。本篇讲述了一些Redis的东西。由于项目本身就是为了学习和练习一些东西。所以,Redis并不是我的强项,只不过随便研究研究,具体专业的用法我也不太会。还在学习中。。。
实现思路
首先,我采用了Redis中的哈希表结构来存储用户的在线信息。如下图所示:key代表userid,value是用户的connectionid。
是不是很简单,那么存储这些数据有什么好处呢,
1.我们可以统计多少在线用户
2.配合前端界面,实现某个好友是否在线
3.判断好友是否在线在决定是否像该好友推送消息(不在线的话,直接存储离线消息就可以)
4.解决前言中存在的问题。对于这个问题详细解释一下,比如A给B发消息,A点击打开了B的窗口,现在A已经加入到组AB中。但是B不在组AB中,所以,B收不到本组的消息。假如A打开B窗口的时候,判断一下A是否在线,如果A在线,那么将A加入到AB组中,也就是多了一步 A=》Group的操作。这样的话,就解决了AB不同组导致收不到消息的问题。详细看下图:
实现细节
我们只要在Hub代码中的建立连接,失去连接,重新连接的方法中添加对当前用户的操作逻辑就可以。
/// <summary> /// 获取当前用户信息 /// </summary> private OnlineUser CurrentOnlineUser { get { return new OnlineUser { connectionid = CurrentConnectId, userid = CurrentUserId }; } } /// <summary> /// 建立连接 /// </summary> /// <returns></returns> public override Task OnConnected() { //将当前用户添加到redis在线用户缓存中 LayIMCache.Instance.OperateOnlineUser(CurrentOnlineUser); return Clients.Caller.receiveMessage("连接成功"); } /// <summary> /// 失去连接 /// </summary> /// <param name="stopCalled"></param> /// <returns></returns> public override Task OnDisconnected(bool stopCalled) { //将当前用户从在线用户列表中剔除 LayIMCache.Instance.OperateOnlineUser(CurrentOnlineUser, isDelete: true); return Clients.Caller.receiveMessage("失去连接"); } /// <summary> /// 重新连接 /// </summary> /// <returns></returns> public override Task OnReconnected() { //将当前用户添加到redis在线用户缓存中 LayIMCache.Instance.OperateOnlineUser(CurrentOnlineUser); return Clients.Caller.receiveMessage("重新连接"); }
这里我用的.NET客户端是 StackExchange.Redis.Extensions.Core ,他其实是在 StackExchange.Redis 的基础上有一层封装。用起来更方便一些,喜欢直接用 StackExchange.Redis 的也没问题。
详细代码如下:
static NewtonsoftSerializer serializer = new NewtonsoftSerializer(); StackExchangeRedisCacheClient cacheClient = new StackExchangeRedisCacheClient(serializer); #region 在线用户处理 public void OperateOnlineUser(OnlineUser user, bool isDelete = false) { if (isDelete) { cacheClient.HashDelete(LayIMConst.LayIM_All_OnlineUsers, user.userid); } else { cacheClient.HashSetAsync(LayIMConst.LayIM_All_OnlineUsers, user.userid, user.connectionid); } } #endregion
当我们刷新页面的时候,会先调用 OnDisconnected 方法,在调用 OnConnected 方法。不过,HashSet方法如果是同一个key,可以覆盖其值。
本篇就到这里了,界面上没有改动,只不过增加了一些基于redis缓存的逻辑。
GitHub:https://github.com/fanpan26/LayIM_NetClient 喜欢的话给一个star吧,谢谢啦。
交流群:145322742
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?