一、通訊模式
以往,我們聊天發消息模式(單體發送消息或通知)-好友(一對一)、群組(一對多),方便管理好友-分組方式。
那么聊天和好友管理參考qq,刷新分組標簽也頁面就會從新加載分組列表和分組內好友列表,
刷新群組標簽頁面就會從新加載群組列表,點擊好友進行聊天從新數據庫里面從新獲取消息(包含已讀和未讀、歷史記錄、其實就是讀取最新的消息-沒有已讀和未讀之說)。
請求無狀態,我們不知道有沒有發送消息,我們就需要實時的監聽有沒有新消息,以往的ajax輪詢,如今的signalr。
二、SignalR的實時模式
用戶通過signalr連接服務器后將會是一種實時的連接,並且保存用戶標識,那么我們就能實時提醒我們是否有新消息和監測用戶是否發送消息。
具體為:
文字說明:1、前端在(指定位置)執行連接signalr會觸發OnConnectedAsync (客戶端連接函數,並保存ConnectionId客戶端標識)。
代碼說明:
/// <summary> /// 客戶端連接的時候調用 /// </summary> /// <returns></returns> public override Task OnConnectedAsync() { var id = this.Context.ConnectionId;//客戶標識 Trace.WriteLine("客戶端連接成功"); return base.OnConnectedAsync(); }//所有鏈接的客戶端都會在這里
signalr有發送消息機制讓我觸發即知道我要發消息,即signalr封裝調用前端的發消息的函數,直接以此為載體將數據發送到服務器上,即觸發服務器內的消息函數。
設想1:
如果沒有此機制(機制必須讓服務器端知道某用戶有消息),僅連接不知道用戶做什么,將完全沒有任何意義。
如果通知你有消息,還去數據庫讀取也將會多此一舉即(用戶發消息觸發機制服務器僅知道有消息,無內容即代碼可為消息機制函數內寫ajax達到觸發服務端有消息過來內容沒傳,內部ajax觸發自己寫的控制器方法存儲消息到數據庫),然后前端有一個signalr有消息通知機制可以抖動效果,你自己再去讀取的這種形式,達到消息體和實時連接完全隔離,消息體的格式很多種、支持文字、圖片、視頻、gif、等等還要根據鏈接各個端支持的資源格式做處理(多個瀏覽器支持的資源格式例如蘋果瀏覽器的視頻資源和google視頻資源),這里實時連接兼容問題-每個瀏覽器支持的實時連接已經工作量不小。
而signar發送消息觸發機制是可以承載消息體資源的,這里官方可能沒刻意提到的它的細節,畢竟瀏覽器都支持,我還支持不了你的消息資源格式嗎,肯定不能呀。
設想2:ConnectionId去綁定用戶昵稱和頭像反之。這里的ConnectionId是繼承Hub類的,在此類都可以訪問,
ConnectionId去綁定用戶昵稱和頭像:
通過觸發OnConnectedAsync,只要鏈接的第一時間從數據庫獲取,並綁定,同時因為ConnectionId一直服務端內的持久存在,綁定的關系,也要持久化在服務端用static或緩存。
用戶昵稱和頭像去綁定ConnectionId:
通過自定義函數,鏈接后,主動觸發,將用戶名和頭像傳到hub內的自定義函數內,獲取並綁定,雷同圖下。
三、處理消息的方式
好友列表和消息列表2種情況
已知道:能獲取所有客戶端的鏈接(這個鏈接會非常大,多少億人的鏈接,但是自己賬戶的人確實很少),
1、所以一個用戶剛登陸的情況:
就要讀取數據庫該用戶所有好友,將鏈接的所有客戶端有該用戶好友的全部點亮。
2、分組也是如上一樣
3、消息的話情況
3、1 一方在線的情況下 通過客戶端發送到我們的Signalr中轉服務中,我們先存儲數據庫設置未讀,在線則推送,否則取消
3、2 上線的情況 客戶 但是 用戶先讀取用戶列表點亮,然后才有消息之說,
判斷是否有未讀消息,有就從數據庫讀取消息並將消息狀態更改已讀。
,然后 根據用戶是否在線,反推送消息讀取成功的id——表示展示效果已讀。 (需要消息知道是否被讀的情況下,執行該操作)
3、消息記錄也是,直接獲取消息記錄,(需要消息知道是否被讀的情況下,執行該操作將消息讀取狀態也獲取)