前言

  上篇的预告好像是“聊天室的小细节,你都注意到了吗?”。今天也是为那篇做铺垫吧。之前的版本有好多问题,比如:当前登录用户是否合法问题,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

ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(八) 之 用 Redis 实现用户在线离线状态消息处理的更多相关文章

  1. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室 实战系列

    ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言  http://www.cnblogs.com/panzi/p/5742089.html ASP.NET S ...

  2. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十二) 代码重构使用反射工厂解耦(一)缓存切换

    前言 上一篇中,我们用了反射工厂来解除BLL和UI层耦合的问题.当然那是最简单的解决方法,再复杂一点的程序可能思路相同,但是在编程细节中需要考虑的就更多了,比如今天我在重构过程中遇到的问题.也是接下来 ...

  3. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言

    前端时间听一个技术朋友说 LayIM 2.0 发布了,听到这个消息抓紧去官网看了一下.(http://layim.layui.com/)哎呀呀,还要购买授权[大家支持一下哦],果断买了企业版,喜欢钻研 ...

  4. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取)

    大家好,本篇是接上一篇 ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言  ASP.NET SignalR WebIM系列第二篇.本篇会带领大家将 LayIM ...

  5. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(二) 之 ChatServer搭建,连接服务器,以及注意事项。

    上篇:ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取) 上一篇我们已经完成了初步界面的搭建工作,本篇将介绍IM的核心内容 ...

  6. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(三) 之 实现单聊,群聊,发送图片,文件。

    上篇讲解了如何搭建聊天服务器,以及客户端js怎么和layui的语法配合.服务器已经连接上了,那么聊天还会远吗? 进入正题,正如上一篇提到的我们用 Client.Group(groupId)的方法向客户 ...

  7. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(四) 之 用户搜索(Elasticsearch),加好友流程(1)。

    前面几篇基本已经实现了大部分即时通讯功能:聊天,群聊,发送文件,图片,消息.不过这些业务都是比较粗犷的.下面我们就把业务细化,之前用的是死数据,那我们就从加好友开始吧.加好友,首先你得知道你要加谁.L ...

  8. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(五) 之 加好友,加群流程,消息管理和即时消息提示的实现

    前言 前前一篇留了个小问题,在上一篇中忘了写了,就是关于LayIM已经封装好的上传文件或者图片的问题.对接好接口之后,如果上传速度慢,界面就会出现假死情况,虽然文件正在上传.于是我就简单做了个图标替代 ...

  9. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(六) 之 Layim源码改造右键菜单--好友、组管理功能的实现。

    前言 上一篇中讲解了加好友的流程,本篇将介绍好友管理,群组管理的右键菜单功能.当然由于菜单项目太多,都实现也得花费时间.只讲解一下我是如何从不知道怎么实现右键菜单到会自定义菜单的一个过程.另外呢,针对 ...

  10. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(七) 之 历史记录查询(时间,关键字,图片,文件),关键字高亮显示。

    前言 上一篇讲解了如何自定义右键菜单,都是前端的内容,本篇内容就一个:查询.聊天历史纪录查询,在之前介绍查找好友的那篇博客里已经提到过 Elasticsearch,今天它又要上场了.对于Elastic ...

随机推荐

  1. Code First06---CodeFirst中的一对多关系

    本章我将介绍Code First将类之间的引用关系映射为数据表之间的一对多关系的默认规则.主要包含以下两部分内容: 1.Code First将类之间的引用关系映射为数据表之间一对多关系的默认规则. 2 ...

  2. utils部分--一些通用的工具类封装

    1.简介 utils部分是对一些常用的工具类进行简单的封装,使用起来比较方便.这里列举常用的一些. 2.ContextUtils使用 主要封装了网络判断.一些方法解释如下: ? 1 2 3 4 5 6 ...

  3. MS Project 使用之创建项目信息

    1. 我们打开MS Project 2013,创建一个空白文档. 2. 切换“项目”选项卡,点击“项目信息”,设置项目开始时间等信息,项目一般是需要设置开始时间和使用日历的,下面我们分别进行设置 如, ...

  4. maven引入jar包时,一个jar的引入错误,会导致后来的jar包的引入。

    maven引入本jar包时,引入失败. 问题是另一个jar没有引入正确.

  5. Android学习笔记(一)——新建一个项目

    //此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 1.打开Android Studio时出现以下界面,点击”start a new Android Studio ...

  6. [KOJ6997]旅行商问题二

    [COJ6997]旅行商问题二 试题描述 Bob是一名旅行商,Bob同时也是一个哲学家,他深知到了一个地方就要掏出钱包把所有景点都玩到.一个城市有N个景点,其中N-1条无向道路链接成一个连通图.Bob ...

  7. 如何用极路由+OpenWrt+RTL电视棒搭建一台SDR服务器,并隐秘地捕获和传输数据

    0×00 前言 近期因为有个从异地捕获无线信号的需求,便尝试着用OpenWrt+公网IP搭建了一台SDR服务器.如果有小伙伴嫌SDR硬件天线看起来太乱.或者电脑没有足够的USB接口也可在局域网搭建SD ...

  8. Tunna内网转发

    Tunna和reduh原理一样.. 使用方法: 上传源码包中文件夹webshell下的脚本至网站目录 然后本地进行连接上传的webshell即可 python proxy.py -u http://1 ...

  9. Python中sorted()方法

    Python中sorted()方法的用法 1.先说一下iterable,中文意思是迭代器. Python的帮助文档中对iterable的解释是:iteralbe指的是能够一次返回它的一个成员的对象.i ...

  10. 常用浏览器user_agent大全

    PC端: safari 5.1 – MACUser-Agent:Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit ...