1、概述

通过前两篇

史上最全面的SignalR系列教程-1、认识SignalR

史上最全面的SignalR系列教程-2、SignalR 实现推送功能-永久连接类实现方式

RDIFramework.NET敏捷开发框架通过SignalR技术整合即时通讯(IM)

文章对SignalR的介绍,我们对SignalR已经有了全面的认识。SignalR API 客户端和服务器端持久连接的通信方式,一次连接代表一个发送单个、分组或者广播消息的简单终端。持久连接的API(表现在.NET的PersistentConnection 类上)给了开发人员低价访问SignalR所暴露的通信协议的条件。使用这种连接方式,就像开发人员使用WCF一样。

本篇将继续在上一篇的基础上,讲解SignalR通过最常用的集线器方式实现消息推送与发送。

我们知道SignalR的通信模型主要是两类Persistent Connections与Hubs。Hub是一种更高级的管道,它在连接协议上允许客户端和服务器端能够直接调用彼此的方法。SignalR的这种自动分发跨机器边界调度的方法就像施了魔法一样,让客户端调用服务端的方法像调用本地一样简单,反之亦然。使用Hub的模式就像开发人员使用远程API一样,比如 .NET Remoting。使用Hub同样能够让你传递类型化的参数到方法上进行模型绑定。通过Hubs实现服务端消息推送到客户端,抽象结构图如下。

2、SignalR Hub 原理分析

SignalR具体是如何到达实行性的呢?SignalR 的实现机制与 .NET WCF 或 Remoting 是相似的,都是使用远程代理来实现。SignalR 将整个连接,信息交换过程封装得非常漂亮,客户端与服务器端全部使用 JSON 来交换数据。

当服务端的代码访问一个客户端的方法时,一个数据包被自动传输,数据包中包含了函数方法参数的名称(如果是一个对象,那么这个对象会被序列化成JSON)。客户端然后根据客户端的代码匹配方法的名称。如果找到相应的匹配方法,那么久调用相应的函数执行反序列化的参数。

3、Hubs实现实时消息流程

  • 在服务器端定义对应的hub class;

  • 在客户端定义hub class 所对应的 proxy 类;

  • 在客户端与服务器端建立连接(connection);

  • 然后客户端就可以调用 proxy 对象的方法来调用服务器端的方法,也就是发送 request 给服务器端;

  • 服务器端接收到 request 之后,可以针对某个/组客户端或所有客户端(广播)发送消息。

4、SignalR的Hub连接类Mvc实现

我们继续在上一篇项目基础上扩展hubs的方式的使用。具体新增项目、添加signalr引用等可以参考上一篇。

4.1、向工程中添加HubConnections目录,在其中添加ChatHub.cs文件,如下图所示:

代码内容如下:

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs; namespace SignalRTestProj.HubConnections
{
//HubName 这个特性是为了让客户端知道如何建立与服务器端对应服务的代理对象,
//如果没有设定该属性,则以服务器端的服务类名字作为 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);
}
}
}

在上面的代码中,实现的服务很简单,就是当一个客户端调用Send方法向服务器发送message后,服务器端负责将该 message广播给所有的客户端(也可以给特定组或特定客户端),以实现聊天室的功能。

除了服务端可以向所有客户端通知调用客户端方法之外,还可以对其中想要发送的客户端进行限制。同时Clients这个属性有很多动态成员供我们使用:

Clients.All:允许“调用”连接到此Hub上的所有客户端的一个方法

Clients.AllExcept:表示该调用必须发送给所有客户端,但是除了那些作为参数的connectionId以外。这里的参数可以是connectionId字符串、数组等

Clients.Caller 确定调用者的接收者是目前调用正在执行Hub方法的客户端

Clients.Client:将对方法的调用发送给指定connectionId的客户端,参数可以是字符串,也可以是数组

Client.Others :代表所有已连接的客户端,但是不包括正在调用该方法的客户端。

在方法中可以通过访问 this.Context.ConnectionId来获得当前掉用方法的客户端唯一标识符

1)、HubName 这个特性是为了让客户端知道如何建立与服务器端对应服务的代理对象,如果没有设定该属性,则以服务器端的服务类名字作为 HubName 的缺省值;

2)、ChatHub 继承自 Hub,从下面 Hub 的接口图可以看出:Hub 支持向发起请求者(Caller),所有客户端(Clients),特定组(Group) 推送消息。

3)、public void Send(string clientName, string message) 这个接口是被客户端通过代理对象调用的;

4)、Clients 是 Hub 的属性,表示所有链接的客户端页面,它和 Caller一样是 dynamic,因为要直接对应到 Javascript 对象;

5)、Clients.All.addSomeMessage(clientName, message): 表示服务器端调用客户端的 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)
{
// 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888
//1、 PersistentConnection 方式配置
//app.MapSignalR<ChatConnection>("/Connections/ChatConnection"); //2、hub方式配置
app.MapSignalR();
}
}
}

4.3、页面代码实现

<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 () {
// 调用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 建立对应服务器端 Hub 类的代理对象 chat;

3、定义客户端的 Javascript 方法 addSomeMessage,服务器通过 dynamic 方式调用客户端的该方法以实现推送功能。在这里每当收到服务器推送来的消息,就在客户端页面的 messages 列表表头插入该消息。

4、当点击广播按钮时,客户端通过代理对象调用服务器端的 send 方法以实现向服务器发送消息。

5、通过 $.connection.hub.start(); 语句打开链接。

5、效果展示

6、代码下载

实例源码可以移步github下载,地址:https://github.com/yonghu86/SignalRTestProj

7、参考文章


一路走来数个年头,感谢RDIFramework.NET框架的支持者与使用者,大家可以通过下面的地址了解详情。

RDIFramework.NET官方网站:http://www.rdiframework.net/

RDIFramework.NET官方博客:http://blog.rdiframework.net/

同时需要说明的,以后的所有技术文章以官方网站为准,欢迎大家收藏!

RDIFramework.NET框架由海南国思软件科技有限公司专业团队长期打造、一直在更新、一直在升级,请放心使用!

欢迎关注RDIFramework.net框架官方公众微信(微信号:guosisoft),及时了解最新动态。

扫描二维码立即关注

史上最全面的SignalR系列教程-3、SignalR 实现推送功能-集线器类实现方式的更多相关文章

  1. 史上最全面的SignalR系列教程-4、SignalR 自托管全解(使用Self-Host)-附各终端详细实例

    1.概述 通过前面几篇文章 史上最全面的SignalR系列教程-1.认识SignalR 史上最全面的SignalR系列教程-2.SignalR 实现推送功能-永久连接类实现方式 史上最全面的Signa ...

  2. 史上最全面的SignalR系列教程-5、SignalR 实现一对一聊天

    1.概述 通过前面几篇文章 史上最全面的SignalR系列教程-1.认识SignalR 史上最全面的SignalR系列教程-2.SignalR 实现推送功能-永久连接类实现方式 史上最全面的Signa ...

  3. 史上最全面的SignalR系列教程-6、SignalR 实现聊天室

    1.概述 通过前面几篇文章对SignalR的详细介绍.我们知道Asp.net SignalR是微软为实现实时通信的一个类库.一般情况下,SignalR会使用JavaScript的长轮询(long po ...

  4. 史上最全面的SignalR系列教程-目录汇总

    1.引言 最遗憾的不是把理想丢在路上,而是理想从未上路. 每一个将想法变成现实的人,都值得称赞和学习. 致正在奔跑的您! 2.SignalR介绍 SignalR实现服务器与客户端的实时通信 ,她是一个 ...

  5. 史上最全面的SignalR系列教程-2、SignalR 实现推送功能-永久连接类实现方式

    1.概述 通过上篇史上最全面的SignalR系列教程-1.认识SignalR文章的介绍,我们对SignalR技术已经有了一个全面的了解.本篇开始就通过SignalR的典型应用的实现方式做介绍,例子虽然 ...

  6. .Net魔法堂:史上最全的ActiveX开发教程——ActiveX与JS间交互篇

    一.前言 经过上几篇的学习,现在我们已经掌握了ActiveX的整个开发过程,但要发挥ActiveX的真正威力,必须依靠JS.下面一起来学习吧! 二.JS调用ActiveX方法 只需在UserContr ...

  7. .Net魔法堂:史上最全的ActiveX开发教程——开发篇

    一.前言 在设计某移动内部自动化运维平台时,经综合考虑终端机性能和功能需求等因素后,决定采用B/S模式,并且浏览器通过ActiveX组件实现与服务器Agent作P2P的通讯.好处,整个平台以网页形式存 ...

  8. .Net魔法堂:史上最全的ActiveX开发教程——自动更新、卸载篇

    一.前言 B/S模式的特点之一,客户端版本升级相对简单.快捷,适合产品的快速迭代.而ActiveX组件的自动更新同样也继承了这一优点.下面我们一起来了解吧! 二.二话不说更新ActiveX 1. 设置 ...

  9. .Net魔法堂:史上最全的ActiveX开发教程——部署篇

    一.前言 接<.Net魔法堂:史上最全的ActiveX开发教程——发布篇>,后我们继续来部署吧! 二. 挽起衣袖来部署   ActiveX的部署其实就是客户端安装ActiveX组件,对未签 ...

随机推荐

  1. VMware下的Centos7实践Kvm虚拟化(通俗易懂)

    虽然网上已经有很多关于kvm安装的教程了,但我还是看得头晕,有的教程里安装的包很多,有的很少,也没说明那些安装包的作用是干嘛的,用的命令也不一样,也没解释命令的意思是什么. 我重新写一个教程,尽量通俗 ...

  2. Spring Boot微服务电商项目开发实战 --- 基础配置及搭建

    根据SpringBoot实现分布式微服务项目近两年的开发经验,今天决定开始做SpringBoot实现分布式微服务项目的系列文章,帮助其他正在使用或计划使用SringBoot开发的小伙伴们.本次系列文章 ...

  3. nginx连接资源管理

    本文介绍在nginx中连接资源(即ngx_connection_t)的管理与使用. 连接池的初始化 在ngx_cycle_t结构体中维护了几个和连接相关的数据,具体如下 struct ngx_cycl ...

  4. 个人永久性免费-Excel催化剂功能第36波-新增序列函数用于生成规律性的循环重复或间隔序列

    啃过Excel函数的表哥表姐们,一定对函数的嵌套.数组公式等高级的应用有很深的体会,威力是大,但也烧死不少脑细胞,不少人就在这样的绕函数中光荣地牺牲了,走向从入门到放弃.Excel催化剂的创立,初衷就 ...

  5. 你真的了解 Cookie 和 Session 吗

    我在做面试官的时候,曾经问过很多朋友这个问题: Cookie 和 Session 有什么区别呢?大部分的面试者应该都可以说上一两句,比如:什么是 Cookie?什么是 Session?两者的区别等. ...

  6. 安装解压版MySQL5.76及以上版本 出现服务正在启动-服务无法启动的问题

     最近重装了系统,去MySQL官网下载了最新的MySQL5.7.9,我选择的是解压版,安装之后启动服务的时候,提示服务无法启动,在网上找了很多教程,弄了很久都没有弄好,后来还是决定去英文官网找找答案, ...

  7. 【git】Git的使用

    一.安装git 1.windows下安装一个Git 2.lInux下yum(apt-get) install git 二.使用git连接github 使用git连接github时,需要将linux下产 ...

  8. luogu题解 P5020 【货币系统 】

    思路 判断钱数是否可以转化为其他钱数的和 与楼下不同,我没有用sort.而是用了一个数组来特判. 思路其实只是简单dp. 详见代码. #include<cstdio> using name ...

  9. 【ironic】ironic介绍与原理

    [ironic]ironic介绍与原理 零,配置文件 0.1 配置驱动 文件ironic.conf, ipmi硬件类型,默认值也是ipmi, pxe_ipmitool驱动也是默认值,配置驱动 [DEF ...

  10. python 文件读写总结

    这是个人在项目中抽取的代码,自己写的utils的通用模块,使用的框架是tronado,包括了文件的读写操作,api格式的统一函数,如有特别需要可以联系我或者自己扩展,刚学python不久,仅供参考,例 ...