前言

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

    转载请注明出处哈:http://carlosfu.iteye.com/blog/2254154 上上周和同事(龙哥)参加了360组织的互联网技术训练营第三期,美团网的DBA负责人侯军伟给大家介绍了美团 ...

  2. div+css模仿登录界面

    我的代码,这种方式形成了遮罩层,遮罩层的"登录"按钮仍可被点击,非我想要的. <!DOCTYPE html> <html lang="en"& ...

  3. Unity手游之路<九>自动寻路Navmesh之高级主题

    http://blog.csdn.net/janeky/article/details/17492531 之前我们一起学习了如何使用Navmesh组件来实现最基本的角色自动寻路.今天我们再继续深入探索 ...

  4. phpcms 根据条件调取内容

    asdasdsd <script> 正则 截取 function getUrlParam(name) { var reg = new RegExp("(^|&)" ...

  5. caffe学习系列(4):视觉层介绍

    视觉层包括Convolution, Pooling, Local Response Normalization (LRN), im2col等层. 这里介绍下conv层. layer { name: & ...

  6. Raspberry Pi 学习笔记之一

    记录几个搭建服务器教程: [教程] 将树莓派变成网络打印机服务器(更新PC和手机端设置)!http://www.eeboard.com/bbs/thread-8818-1-1.html[心得] [分享 ...

  7. BZOJ 1922: [Sdoi2010]大陆争霸

    Description 一个无向图,到一个点之前需要先到其他点,求从第一个点到第 \(n\) 点最短时间. Sol 拓扑+Dijkstra. 跑Dijkstra的时候加上拓扑序... 用两个数组表示 ...

  8. 为什么要继承ActionSupport?

    struts2中的action可以继承ActionSupport,也可以不继承ActionSupport.不继承ActionSupport的情况只需要有一个方法,返回String,即可,记住,在继承A ...

  9. MappingJacksonHttpMessageConverter过期

    最新在做一个SSM整合学习项目,maven加上jackson库,spring配置json,tomcat不能正常部署启动 Maven配置 <!-- 引入jackson,防止ajax调用返回json ...

  10. [20160804]synchronized

    class Timer{ private static int num; void add(String name){ //synchronized (this){ num++; try{ Threa ...