史上最全面的SignalR系列教程-3、SignalR 實(shí)現(xiàn)推送功能-集線器類實(shí)現(xiàn)方式
1、概述
通過前兩篇
史上最全面的SignalR系列教程-1、認(rèn)識SignalR
史上最全面的SignalR系列教程-2、SignalR 實(shí)現(xiàn)推送功能-永久連接類實(shí)現(xiàn)方式
RDIFramework.NET敏捷開發(fā)框架通過SignalR技術(shù)整合即時通訊(IM)
文章對SignalR的介紹,我們對SignalR已經(jīng)有了全面的認(rèn)識。SignalR API 客戶端和服務(wù)器端持久連接的通信方式,一次連接代表一個發(fā)送單個、分組或者廣播消息的簡單終端。持久連接的API(表現(xiàn)在.NET的PersistentConnection 類上)給了開發(fā)人員低價訪問SignalR所暴露的通信協(xié)議的條件。使用這種連接方式,就像開發(fā)人員使用WCF一樣。
本篇將繼續(xù)在上一篇的基礎(chǔ)上,講解SignalR通過最常用的集線器方式實(shí)現(xiàn)消息推送與發(fā)送。
我們知道SignalR的通信模型主要是兩類Persistent Connections與Hubs。Hub是一種更高級的管道,它在連接協(xié)議上允許客戶端和服務(wù)器端能夠直接調(diào)用彼此的方法。SignalR的這種自動分發(fā)跨機(jī)器邊界調(diào)度的方法就像施了魔法一樣,讓客戶端調(diào)用服務(wù)端的方法像調(diào)用本地一樣簡單,反之亦然。使用Hub的模式就像開發(fā)人員使用遠(yuǎn)程API一樣,比如 .NET Remoting。使用Hub同樣能夠讓你傳遞類型化的參數(shù)到方法上進(jìn)行模型綁定。通過Hubs實(shí)現(xiàn)服務(wù)端消息推送到客戶端,抽象結(jié)構(gòu)圖如下。

2、SignalR Hub 原理分析
SignalR具體是如何到達(dá)實(shí)行性的呢?SignalR 的實(shí)現(xiàn)機(jī)制與 .NET WCF 或 Remoting 是相似的,都是使用遠(yuǎn)程代理來實(shí)現(xiàn)。SignalR 將整個連接,信息交換過程封裝得非常漂亮,客戶端與服務(wù)器端全部使用 JSON 來交換數(shù)據(jù)。
當(dāng)服務(wù)端的代碼訪問一個客戶端的方法時,一個數(shù)據(jù)包被自動傳輸,數(shù)據(jù)包中包含了函數(shù)方法參數(shù)的名稱(如果是一個對象,那么這個對象會被序列化成JSON)。客戶端然后根據(jù)客戶端的代碼匹配方法的名稱。如果找到相應(yīng)的匹配方法,那么久調(diào)用相應(yīng)的函數(shù)執(zhí)行反序列化的參數(shù)。
3、Hubs實(shí)現(xiàn)實(shí)時消息流程
-
在服務(wù)器端定義對應(yīng)的hub class;
-
在客戶端定義hub class 所對應(yīng)的 proxy 類;
-
在客戶端與服務(wù)器端建立連接(connection);
-
然后客戶端就可以調(diào)用 proxy 對象的方法來調(diào)用服務(wù)器端的方法,也就是發(fā)送 request 給服務(wù)器端;
-
服務(wù)器端接收到 request 之后,可以針對某個/組客戶端或所有客戶端(廣播)發(fā)送消息。

4、SignalR的Hub連接類Mvc實(shí)現(xiàn)
我們繼續(xù)在上一篇項目基礎(chǔ)上擴(kuò)展hubs的方式的使用。具體新增項目、添加signalr引用等可以參考上一篇。
4.1、向工程中添加HubConnections目錄,在其中添加ChatHub.cs文件,如下圖所示:

代碼內(nèi)容如下:
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
namespace SignalRTestProj.HubConnections
{
//HubName 這個特性是為了讓客戶端知道如何建立與服務(wù)器端對應(yīng)服務(wù)的代理對象,
//如果沒有設(shè)定該屬性,則以服務(wù)器端的服務(wù)類名字作為 HubName 的缺省值
[HubName("chat")]
public class ChatHub : Hub
{
public void Send(string clientName, string message)
{
// Call the addSomeMessage method to update clients.
Clients.All.addSomeMessage(clientName, message);
}
}
}
在上面的代碼中,實(shí)現(xiàn)的服務(wù)很簡單,就是當(dāng)一個客戶端調(diào)用Send方法向服務(wù)器發(fā)送message后,服務(wù)器端負(fù)責(zé)將該 message廣播給所有的客戶端(也可以給特定組或特定客戶端),以實(shí)現(xiàn)聊天室的功能。
除了服務(wù)端可以向所有客戶端通知調(diào)用客戶端方法之外,還可以對其中想要發(fā)送的客戶端進(jìn)行限制。同時Clients這個屬性有很多動態(tài)成員供我們使用:
Clients.All:允許“調(diào)用”連接到此Hub上的所有客戶端的一個方法
Clients.AllExcept:表示該調(diào)用必須發(fā)送給所有客戶端,但是除了那些作為參數(shù)的connectionId以外。這里的參數(shù)可以是connectionId字符串、數(shù)組等
Clients.Caller 確定調(diào)用者的接收者是目前調(diào)用正在執(zhí)行Hub方法的客戶端
Clients.Client:將對方法的調(diào)用發(fā)送給指定connectionId的客戶端,參數(shù)可以是字符串,也可以是數(shù)組
Client.Others :代表所有已連接的客戶端,但是不包括正在調(diào)用該方法的客戶端。
在方法中可以通過訪問 this.Context.ConnectionId來獲得當(dāng)前掉用方法的客戶端唯一標(biāo)識符
1)、HubName 這個特性是為了讓客戶端知道如何建立與服務(wù)器端對應(yīng)服務(wù)的代理對象,如果沒有設(shè)定該屬性,則以服務(wù)器端的服務(wù)類名字作為 HubName 的缺省值;
2)、ChatHub 繼承自 Hub,從下面 Hub 的接口圖可以看出:Hub 支持向發(fā)起請求者(Caller),所有客戶端(Clients),特定組(Group) 推送消息。

3)、public void Send(string clientName, string message) 這個接口是被客戶端通過代理對象調(diào)用的;
4)、Clients 是 Hub 的屬性,表示所有鏈接的客戶端頁面,它和 Caller一樣是 dynamic,因?yàn)橐苯訉?yīng)到 Javascript 對象;
5)、Clients.All.addSomeMessage(clientName, message): 表示服務(wù)器端調(diào)用客戶端的 addSomeMessage 方法,這是一個 Javascript 方法,從而給客戶端推送消息。
4.2、配置啟動類
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(SignalRTestProj.App_Start.ChartStartup))]
namespace SignalRTestProj.App_Start
{
public class ChartStartup
{
public void Configuration(IAppBuilder app)
{
// 有關(guān)如何配置應(yīng)用程序的詳細(xì)信息,請訪問 https://go.microsoft.com/fwlink/?LinkID=316888
//1、 PersistentConnection 方式配置
//app.MapSignalR<ChatConnection>("/Connections/ChatConnection");
//2、hub方式配置
app.MapSignalR();
}
}
}
4.3、頁面代碼實(shí)現(xiàn)
<h2>Hub Chat</h2>
<div>
<input type="hidden" id="ClientName" value="@ViewBag.ClientName"/>
<input type="text" id="msg" />
<input type="button" id="broadcast" value="廣播" />
<br />
<h3>
(<span id="MyClientName">@ViewBag.ClientName</span>):
</h3>
<ul id="messages"></ul>
</div>
@section scripts {
<script src="~/Scripts/jquery-3.3.1.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.4.1.min.js"></script>
<script src="~/signalr/hubs"></script>
<script>
$(function () {
var chat = $.connection.chat;
var myClientName = $('#ClientName').val();
chat.client.addSomeMessage = function (clientName, message) {
writeMsg('<b>' + clientName + '</b> 對大家說: ' + message, 'event-message');
};
$('#msg').focus();
// 開始連接
$.connection.hub.start().done(function () {
$('#broadcast').click(function () {
// 調(diào)用send方法
chat.server.send(myClientName, $('#msg').val());
$('#msg').val('').focus();
});
});
//寫消息
function writeMsg(eventLog, logClass) {
var now = new Date();
var nowStr = now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds();
$('#messages').prepend('<li class="' + logClass + '"><b>' + nowStr + '</b> ' + eventLog + '.</li>');
}
});
</script>
}
在上面的代碼我們
1、首先獲取客戶端頁面的名字;
2、然后通過 $.connection.chat 建立對應(yīng)服務(wù)器端 Hub 類的代理對象 chat;
3、定義客戶端的 Javascript 方法 addSomeMessage,服務(wù)器通過 dynamic 方式調(diào)用客戶端的該方法以實(shí)現(xiàn)推送功能。在這里每當(dāng)收到服務(wù)器推送來的消息,就在客戶端頁面的 messages 列表表頭插入該消息。
4、當(dāng)點(diǎn)擊廣播按鈕時,客戶端通過代理對象調(diào)用服務(wù)器端的 send 方法以實(shí)現(xiàn)向服務(wù)器發(fā)送消息。
5、通過 $.connection.hub.start(); 語句打開鏈接。
5、效果展示

6、代碼下載
實(shí)例源碼可以移步github下載,地址:https://github.com/yonghu86/SignalRTestProj
7、參考文章
-
史上最全面的SignalR系列教程-2、SignalR 實(shí)現(xiàn)推送功能-永久連接類實(shí)現(xiàn)方式
-
RDIFramework.NET框架SOA解決方案(集Windows服務(wù)、WinForm形式與IIS形式發(fā)布)-分布式應(yīng)用
一路走來數(shù)個年頭,感謝RDIFramework.NET框架的支持者與使用者,大家可以通過下面的地址了解詳情。
RDIFramework.NET官方網(wǎng)站:http://www.rdiframework.net/
RDIFramework.NET官方博客:http://blog.rdiframework.net/
同時需要說明的,以后的所有技術(shù)文章以官方網(wǎng)站為準(zhǔn),歡迎大家收藏!
RDIFramework.NET框架由海南國思軟件科技有限公司專業(yè)團(tuán)隊長期打造、一直在更新、一直在升級,請放心使用!
歡迎關(guān)注RDIFramework.net框架官方公眾微信(微信號:guosisoft),及時了解最新動態(tài)。
掃描二維碼立即關(guān)注

作者:
RDIF
出處:
http://www.rzrgm.cn/huyong/
Email:
406590790@qq.com
QQ:
406590790
微信:
13005007127(同手機(jī)號)
框架官網(wǎng):
http://www.guosisoft.com/
http://www.rdiframework.net/
框架其他博客:
http://blog.csdn.net/chinahuyong
http://www.rzrgm.cn/huyong
國思RDIF開發(fā)框架
,
給用戶和開發(fā)者最佳的.Net框架平臺方案,為企業(yè)快速構(gòu)建跨平臺、企業(yè)級的應(yīng)用提供強(qiáng)大支持。
關(guān)于作者:系統(tǒng)架構(gòu)師、信息系統(tǒng)項目管理師、DBA。專注于微軟平臺項目架構(gòu)、管理和企業(yè)解決方案,多年項目開發(fā)與管理經(jīng)驗(yàn),曾多次組織并開發(fā)多個大型項目,在面向?qū)ο蟆⒚嫦蚍?wù)以及數(shù)據(jù)庫領(lǐng)域有一定的造詣。現(xiàn)主要從事基于
RDIF
框架的技術(shù)開發(fā)、咨詢工作,主要服務(wù)于金融、醫(yī)療衛(wèi)生、鐵路、電信、物流、物聯(lián)網(wǎng)、制造、零售等行業(yè)。
如有問題或建議,請多多賜教!
本文版權(quán)歸作者和CNBLOGS博客共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,如有問題,可以通過微信、郵箱、QQ等聯(lián)系我,非常感謝。

本篇將繼續(xù)在上一篇的基礎(chǔ)上,講解SignalR通過最常用的集線器方式實(shí)現(xiàn)消息推送與發(fā)送。
我們知道SignalR的通信模型主要是兩類Persistent Connections與Hubs。Hub是一種更高級的管道,它在連接協(xié)議上允許客戶端和服務(wù)器端能夠直接調(diào)用彼此的方法。SignalR的這種自動分發(fā)跨機(jī)器邊界調(diào)度的方法就像施了魔法一樣,讓客戶端調(diào)用服務(wù)端的方法像調(diào)用本地一樣簡單,反之亦然。使用Hub的模式就像開發(fā)人員使用遠(yuǎn)程API一樣,比如 .NET Remoting。使用Hub同樣能夠讓你傳遞類型化的參數(shù)到方法上進(jìn)行模型綁定。通過Hubs實(shí)現(xiàn)服務(wù)端消息推送到客戶端
浙公網(wǎng)安備 33010602011771號