Web实时通信,SignalR真香,不用愁了
前言
對于B/S模式的項(xiàng)目,基礎(chǔ)的場景都是客戶端發(fā)起請求,服務(wù)端返回響應(yīng)結(jié)果就結(jié)束了一次連接;但在很多實(shí)際應(yīng)用場景中,這種簡單的請求和響應(yīng)模式就顯得很吃力,比如消息通知、監(jiān)控看板信息自動(dòng)刷新等實(shí)時(shí)通信場景,小伙伴們肯定會想到輪詢或WebSocket的方式來搞定,可是單純用輪詢的方式有點(diǎn)耗資源,只用WebSocket的方式又有些瀏覽器或其他客戶端不支持,所以如果自己從頭來寫的話,很多細(xì)節(jié)還得做處理;這個(gè)時(shí)候SignalR就該站出來了,封裝的很給力,直接使用就行。
正文
1. SignalR簡介
SignalR是一個(gè)開源的庫,跨平臺;讓W(xué)eb應(yīng)用與其他應(yīng)用通訊變得很簡單,Web服務(wù)端可以實(shí)時(shí)的將內(nèi)容推送給對應(yīng)的客戶端,客戶端發(fā)送的信息也可以實(shí)時(shí)到其他客戶端。
SignalR提供了一種遠(yuǎn)程過程調(diào)用(RPC)的方式,使得客戶端可以調(diào)用服務(wù)器的方法,同樣在服務(wù)器端的方法中也能調(diào)用客戶端的方法。
1.1 SignalR的通信方式
SignalR支持如下的方式實(shí)現(xiàn)實(shí)時(shí)通信:
WebSockets:是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的協(xié)議,使得服務(wù)器和瀏覽器的通信更加簡單,服務(wù)端可以主動(dòng)發(fā)送信息。
Server-Sent Events:SSE 與 WebSocket 作用相似,都是建立瀏覽器與服務(wù)器之間的通信渠道,然后服務(wù)器向?yàn)g覽器推送信息。WebSocket是雙向的,而SSE是單向的。
Long Polling(長輪詢) :和傳統(tǒng)的輪詢原理一樣,只是服務(wù)端不會每次都返回響應(yīng)信息,只有有數(shù)據(jù)或超時(shí)了才會返回,從而減少了請求次數(shù)。
SignalR會自動(dòng)選擇服務(wù)器和客戶端能力范圍內(nèi)的最佳通信方式(是不是很優(yōu)秀) ,當(dāng)然也可以手動(dòng)指定。
1.2 SignalR的應(yīng)用場景
其實(shí)對于Web模式下的實(shí)時(shí)通信,SignalR用上試試,感覺還是很給力的。
服務(wù)端主動(dòng)推送信息;比如發(fā)送公告場景;
監(jiān)控或看板數(shù)據(jù)實(shí)時(shí)顯示;比如監(jiān)控系統(tǒng)實(shí)時(shí)展示分布到各個(gè)客戶端上的數(shù)據(jù);
服務(wù)端和客戶端交互;比如客服系統(tǒng)的聊天場景。
理論大概先說這么多,接下來就用實(shí)例演示一波。
2. 案例演示
2.1 SignalR服務(wù)端
這里我把SignalR的服務(wù)端寄宿在WebAPI項(xiàng)目中了,實(shí)際可以根據(jù)需要寄宿到對應(yīng)的項(xiàng)目(窗體應(yīng)用、后臺服務(wù)),當(dāng)然也可以單獨(dú)為其創(chuàng)建一個(gè)項(xiàng)目,但代碼編寫都基本一樣。
創(chuàng)建一個(gè)WebAPI項(xiàng)目,引入對應(yīng)的Nuget包
編寫自己的SignalR Hub
Hub就是一個(gè)類,只是里面編寫的方法客戶端可以遠(yuǎn)程調(diào)用到(原理后續(xù)咱們一起讀讀源碼);同樣在服務(wù)端也可以遠(yuǎn)程用客戶端的方法,這樣就使得實(shí)時(shí)通信變得簡單便捷了。
在Startup.cs文件中注冊相關(guān)服務(wù)及管道
業(yè)務(wù)API編寫,推送消息
其實(shí)上面的步驟已經(jīng)完成SignalR服務(wù)端搭建,接下來需要加入一些業(yè)務(wù)模擬,比如模擬消息推送,方便演示;如下編寫API:
到這服務(wù)端的業(yè)務(wù)就寫完了,接下來就是開始編寫客戶端。
2.2 JS客戶端
Js客戶端使用Vue組件,綁定數(shù)據(jù)方便;放在WebApi項(xiàng)目的wwwroot目錄下,和WebAPI一起共用服務(wù)器啟動(dòng),所以就不用考慮跨域問題。如果前端分開部署,需要在SignalR寄宿的項(xiàng)目中配置跨域。具體步驟如下:
獲取signalr封裝好的js文件,開箱即用
npm?init?-y npm?install?@microsoft/signalrnpm將包內(nèi)容安裝在當(dāng)前執(zhí)行命令目錄下的node_modules\@microsoft\signalr\dist\browser文件夾中。在服務(wù)端項(xiàng)目中創(chuàng)建wwwroot/signalr文件夾,將下載下來signalr.js文件復(fù)制到wwwroot\signalr文件夾即可;
采用npm的方式需要提前安裝node,也可以直接下載。不過在真正前端項(xiàng)目中,npm安裝完直接引入就使用了,不需要來回拷貝,這里只是演示。
編寫index.html
這里把所有的靜態(tài)文件都放在WebAPI項(xiàng)目的wwwroot目錄下,到時(shí)候一塊共用服務(wù)器;另外使用到Vue和異步請求,所以需要引入Vue和axios的js文件,這里都是通過CDN地址形式引入,并沒有下載到本地,真實(shí)項(xiàng)目中肯定是要自己管理的。如下:
關(guān)鍵腳本邏輯,如下:
注:這里需要注意客戶端指定的方法名和接到的參數(shù)的解析,是駝峰的形式。
運(yùn)行起來演示發(fā)布效果,如下:
是不是很簡單就實(shí)現(xiàn)了推送效果,根本就沒咋敲代碼,是不是很香。到這小伙伴會問,其他客戶端類型支持嗎?答案是肯定的,什么后臺服務(wù)或窗體都行,接下來就搞個(gè)窗體的客戶端。對了,Java客戶端也支持,只管放心用,不僅僅是.Net。
注:有小伙伴自己開發(fā)運(yùn)行的時(shí)候訪問不到頁面,那因?yàn)閃ebApi項(xiàng)目中默認(rèn)不支持靜態(tài)頁面訪問,需要加上對應(yīng)的中間件,如下:
2.3 WinForm客戶端
布局很簡單,在窗體中直接搞個(gè)文本框顯示消息就行;小伙伴們別嫌棄啊,主要體現(xiàn)的是流程,界面美化小伙伴們自己想怎么搞都行。
核心代碼如下:
客戶端又很輕松的搞定了,運(yùn)行起來看看效果:
先把服務(wù)器運(yùn)行起來(這里是WebApi項(xiàng)目),然后窗體程序運(yùn)行起來:
實(shí)現(xiàn)起來是不是很給力,現(xiàn)在不用再苦惱對于B/S模式下,服務(wù)器端主動(dòng)的場景了吧;
2.4 客戶端主動(dòng)上報(bào)數(shù)據(jù)信息,實(shí)時(shí)顯示到其他客戶端
上面的推送場景是服務(wù)端主動(dòng), 但有很多場景是客戶端主動(dòng)上報(bào)數(shù)據(jù),需要實(shí)時(shí)顯示到數(shù)據(jù)看板或顯示到其他客戶端界面。比如一些監(jiān)控系統(tǒng),需要實(shí)時(shí)顯示設(shè)備狀態(tài);再比如類似游戲的場景,其中一個(gè)客戶端發(fā)生改變,需要實(shí)時(shí)顯示到其他客戶端。
對應(yīng)客戶端主動(dòng)上報(bào)的場景,需要通過服務(wù)器轉(zhuǎn)發(fā),因?yàn)榭蛻舳酥g沒有建立連接,只有服務(wù)器知道有多少客戶端已連上,所以這個(gè)時(shí)候需要在服務(wù)端上增加一個(gè)方法供客戶端調(diào)用,如下步驟:
服務(wù)端在自定義的MyHub中增加一個(gè)方法
這里模擬的是在窗體客戶端發(fā)生數(shù)據(jù)改變,實(shí)時(shí)顯示到其他客戶端
在窗體客戶端按鈕的點(diǎn)擊事件中直接調(diào)用服務(wù)端的方法,并傳遞更新的信息,由服務(wù)端調(diào)用客戶端的方法再轉(zhuǎn)發(fā)給其他客戶端。
客戶端的更新方法,這里只在Js客戶端實(shí)現(xiàn),其他客戶端如果需要,同理
運(yùn)行起來看效果
2.5 小結(jié)
上面列舉了兩個(gè)場景,服務(wù)器主動(dòng)推和客戶端主動(dòng)推兩種情況,基本上可以滿足大多數(shù)實(shí)時(shí)需求。通信流程圖如下:
服務(wù)端推送消息
1.Js客戶端點(diǎn)擊發(fā)布按鈕調(diào)用API接口;
2.接口內(nèi)部將信息交給SignalR處理;
3.獲取所有客戶端,并通過遠(yuǎn)程調(diào)用客戶端方法的方式將信息傳遞給客戶端,最后信息就可以實(shí)時(shí)展示了。
客戶端上報(bào)數(shù)據(jù)
1.在窗體客戶端中點(diǎn)擊按鈕,內(nèi)部調(diào)用服務(wù)端的UpdateDataServer方法;
2.服務(wù)端被調(diào)用之后,內(nèi)部獲取所有客戶端,并調(diào)用客戶端中updatedata方法;最后在客戶端將信息展示。
案例源碼地址:https://gitee.com/CodeZoe/dot-net-core-study-demo/tree/main/SignalRDemo
總結(jié)
關(guān)于SignalR的簡單使用先說這么多,便捷又好用;還有一些關(guān)鍵的知識點(diǎn)后續(xù)會分享,比如針對分組和用戶發(fā)信息、添加認(rèn)證管理等,關(guān)注“Code綜藝圈”,和我一起學(xué)習(xí)吧;
總結(jié)
以上是生活随笔為你收集整理的Web实时通信,SignalR真香,不用愁了的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: System.Text.Json 中的字
- 下一篇: c#10:string内插处理