Web 實時通信,SignalR 真香,不用愁了
前言
對於 B/S 模式的項目,基礎的場景都是客戶端發起請求,服務端返回響應結果就結束了一次連接;但在很多實際應用場景中,這種簡單的請求和響應模式就顯得很喫力,比如消息通知、監控看板信息自動刷新等實時通信場景,小夥伴們肯定會想到輪詢或 WebSocket 的方式來搞定,可是單純用輪詢的方式有點耗資源,只用 WebSocket 的方式又有些瀏覽器或其他客戶端不支持,所以如果自己從頭來寫的話,很多細節還得做處理;這個時候 SignalR 就該站出來了,封裝的很給力,直接使用就行。
正文
1. SignalR 簡介
SignalR 是一個開源的庫,跨平臺;讓 Web 應用與其他應用通訊變得很簡單,Web 服務端可以實時的將內容推送給對應的客戶端,客戶端發送的信息也可以實時到其他客戶端。
SignalR 提供了一種遠程過程調用 (RPC) 的方式,使得客戶端可以調用服務器的方法,同樣在服務器端的方法中也能調用客戶端的方法。
1.1 SignalR 的通信方式
SignalR 支持如下的方式實現實時通信:
-
WebSockets:是一種在單個 TCP 連接上進行全雙工通信的協議,使得服務器和瀏覽器的通信更加簡單,服務端可以主動發送信息。
-
Server-Sent Events:SSE 與 WebSocket 作用相似,都是建立瀏覽器與服務器之間的通信渠道,然後服務器向瀏覽器推送信息。WebSocket 是雙向的,而 SSE 是單向的。
-
Long Polling(長輪詢) :和傳統的輪詢原理一樣,只是服務端不會每次都返回響應信息,只有有數據或超時了纔會返回,從而減少了請求次數。
SignalR 會自動選擇服務器和客戶端能力範圍內的最佳通信方式 (是不是很優秀) ,當然也可以手動指定。
1.2 SignalR 的應用場景
其實對於 Web 模式下的實時通信,SignalR 用上試試,感覺還是很給力的。
-
服務端主動推送信息;比如發送公告場景;
-
監控或看板數據實時顯示;比如監控系統實時展示分佈到各個客戶端上的數據;
-
服務端和客戶端交互;比如客服系統的聊天場景。
理論大概先說這麼多,接下來就用實例演示一波。
2. 案例演示
2.1 SignalR 服務端
這裏我把 SignalR 的服務端寄宿在 WebAPI 項目中了,實際可以根據需要寄宿到對應的項目 (窗體應用、後臺服務),當然也可以單獨爲其創建一個項目,但代碼編寫都基本一樣。
-
創建一個 WebAPI 項目,引入對應的 Nuget 包
-
編寫自己的 SignalR Hub
Hub 就是一個類,只是裏面編寫的方法客戶端可以遠程調用到 (原理後續咱們一起讀讀源碼);同樣在服務端也可以遠程用客戶端的方法,這樣就使得實時通信變得簡單便捷了。
-
在 Startup.cs 文件中註冊相關服務及管道
-
業務 API 編寫,推送消息
其實上面的步驟已經完成 SignalR 服務端搭建,接下來需要加入一些業務模擬,比如模擬消息推送,方便演示;如下編寫 API:
到這服務端的業務就寫完了,接下來就是開始編寫客戶端。
2.2 JS 客戶端
Js 客戶端使用 Vue 組件,綁定數據方便;放在 WebApi 項目的 wwwroot 目錄下,和 WebAPI 一起共用服務器啓動,所以就不用考慮跨域問題。如果前端分開部署,需要在 SignalR 寄宿的項目中配置跨域。具體步驟如下:
-
獲取 signalr 封裝好的 js 文件,開箱即用
npm init -y npm install @microsoft/signalr
npm 將包內容安裝在當前執行命令目錄下的 node_modules@microsoft\signalr\dist\browser 文件夾中。在服務端項目中創建 wwwroot/signalr 文件夾,將下載下來 signalr.js 文件複製到 wwwroot\signalr 文件夾即可;
採用 npm 的方式需要提前安裝 node,也可以直接下載。不過在真正前端項目中,npm 安裝完直接引入就使用了,不需要來回拷貝,這裏只是演示。
-
編寫 index.html
這裏把所有的靜態文件都放在 WebAPI 項目的 wwwroot 目錄下,到時候一塊共用服務器;另外使用到 Vue 和異步請求,所以需要引入 Vue 和 axios 的 js 文件,這裏都是通過 CDN 地址形式引入,並沒有下載到本地,真實項目中肯定是要自己管理的。如下:
關鍵腳本邏輯,如下:
注:這裏需要注意客戶端指定的方法名和接到的參數的解析,是駝峯的形式。
-
運行起來演示發佈效果,如下:
是不是很簡單就實現了推送效果,根本就沒咋敲代碼,是不是很香。到這小夥伴會問,其他客戶端類型支持嗎?答案是肯定的,什麼後臺服務或窗體都行,接下來就搞個窗體的客戶端。對了,Java 客戶端也支持,只管放心用,不僅僅是. Net。
注:有小夥伴自己開發運行的時候訪問不到頁面,那因爲 WebApi 項目中默認不支持靜態頁面訪問,需要加上對應的中間件,如下:
2.3 WinForm 客戶端
佈局很簡單,在窗體中直接搞個文本框顯示消息就行;小夥伴們別嫌棄啊,主要體現的是流程,界面美化小夥伴們自己想怎麼搞都行。
核心代碼如下:
客戶端又很輕鬆的搞定了,運行起來看看效果:
先把服務器運行起來 (這裏是 WebApi 項目),然後窗體程序運行起來:
實現起來是不是很給力,現在不用再苦惱對於 B/S 模式下,服務器端主動的場景了吧;
2.4 客戶端主動上報數據信息,實時顯示到其他客戶端
上面的推送場景是服務端主動, 但有很多場景是客戶端主動上報數據,需要實時顯示到數據看板或顯示到其他客戶端界面。比如一些監控系統,需要實時顯示設備狀態;再比如類似遊戲的場景,其中一個客戶端發生改變,需要實時顯示到其他客戶端。
對應客戶端主動上報的場景,需要通過服務器轉發,因爲客戶端之間沒有建立連接,只有服務器知道有多少客戶端已連上,所以這個時候需要在服務端上增加一個方法供客戶端調用,如下步驟:
-
服務端在自定義的 MyHub 中增加一個方法
-
這裏模擬的是在窗體客戶端發生數據改變,實時顯示到其他客戶端
在窗體客戶端按鈕的點擊事件中直接調用服務端的方法,並傳遞更新的信息,由服務端調用客戶端的方法再轉發給其他客戶端。
-
客戶端的更新方法,這裏只在 Js 客戶端實現,其他客戶端如果需要,同理
-
運行起來看效果
2.5 小結
上面列舉了兩個場景,服務器主動推和客戶端主動推兩種情況,基本上可以滿足大多數實時需求。通信流程圖如下:
-
服務端推送消息
1.Js 客戶端點擊發布按鈕調用 API 接口;
-
接口內部將信息交給 SignalR 處理;
-
獲取所有客戶端,並通過遠程調用客戶端方法的方式將信息傳遞給客戶端,最後信息就可以實時展示了。
-
-
客戶端上報數據
-
在窗體客戶端中點擊按鈕,內部調用服務端的 UpdateDataServer 方法;
-
服務端被調用之後,內部獲取所有客戶端,並調用客戶端中 updatedata 方法;最後在客戶端將信息展示。
-
案例源碼地址:https://gitee.com/CodeZoe/dot-net-core-study-demo/tree/main/SignalRDemo
總結
關於 SignalR 的簡單使用先說這麼多,便捷又好用;還有一些關鍵的知識點後續會分享,比如針對分組和用戶發信息、添加認證管理等,關注 “Code 綜藝圈”,和我一起學習吧;
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/La_H_Vc_duCggkyHZT3qTA