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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM