背景:Web端需要能实时接收到消息推送,当客户有新消息来时,在客户端的右下角进行弹框提醒。
什么是signalR?
Asp.net SignalR是微软为实现实时通信的一个类库。一般情况下,signalR会使用JavaScript的长轮询(long polling)的方式来实现客户端和服务器通信,随着Html5中WebSockets出现,SignalR也支持WebSockets通信。另外SignalR开发的程序不仅仅限制于宿主在IIS中,也可以宿主在任何应用程序,包括控制台,客户端程序和Windows服务等,另外还支持Mono,这意味着它可以实现跨平台部署在Linux环境下。
signalR内部有两类对象:
Http持久连接(Persisten Connection)对象:用来解决长时间连接的功能。还可以由客户端主动向服务器要求数据,而服务器端不需要实现太多细节,只需要处理PersistentConnection 内所提供的五个事件:OnConnected, OnReconnected, OnReceived, OnError 和 OnDisconnect 即可。
Hub(集线器)对象:用来解决实时(realtime)信息交换的功能,服务端可以利用URL来注册一个或多个Hub,只要连接到这个Hub,就能与所有的客户端共享发送到服务器上的信息,同时服务端可以调用客户端的脚本。SignalR将整个信息的交换封装起来,客户端和服务器都是使用JSON来沟通的,在服务端声明的所有Hub信息,都会生成JavaScript输出到客户端,.NET则依赖Proxy来生成代理对象,而Proxy的内部则是将JSON转换成对象。
SignalR将整个信息的交换封装起来,客户端和服务器都是使用JSON来沟通的,在服务端声明的所有Hub信息,都会生成JavaScript输出到客户端,.NET则依赖Proxy来生成代理对象,而Proxy的内部则是将JSON转换成对象。
客户端和服务端的具体交互情况如下图所示:
基本流程如图:
其实说白点SignalR其实就是微软自己封装好的实现即时通讯的一个类库
如何使用:
Nuget引入 Microsoft.AspNet.SignalR 系列 2.4.1
添加完signalR你可以在 Scripts 文件夹下看到自动添加了两个js文件:
向项目中添加一个signalR集线器(V2)命名为ServerHub:
在刚刚新建的ServerHub.cs 中写入 一下代码:
//*********************************************************************************
//Description:自定义扩展一个消息通知类库模块>集线器
//Author:DennyHui
//Create Date: 2019年10月15日18:39:33
//*********************************************************************************
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
namespace Fisk.DataWithReportManage.AutoTask
{
///
/// 消息通知集线器 2019年10月16日12:28:08 Dennyhui
///
[HubName("serverhub")]
public class ServerHub:Hub
{
///
/// 发送消息 2019年10月16日12:28:18 Dennyhui
///
///
public void SendMsg(string id,string title, string message,string poptype)
{
//调用所有客户端的sendMessage方法(sendMessage有2个参数)
//Clients.All.SendMessage("测试");
//Clients.All.broadcastMessage("测试");
//Clients.All.notify("测试");
var hubContext = GlobalHost.ConnectionManager.GetHubContext();//此处的“ServerHub”需要和当前的类名一直
hubContext.Clients.All.sendMessage(id,title,message, poptype); //用户调用客户端的函数
//Clients.All.sendMessage(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), "测试");
}
///
/// 实例化 2019年10月16日12:28:31 Dennhui
///
public void Init() { }
}
}
如果你的mvc项目是不进行身份验证的那种吧,必须得添加一个Startup 类. 如果没有这个类,请添加,不然的话项目运行不起来的,具体代码如下:
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(SignalRQuickStart.Startup))]
namespace SignalRQuickStart
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888
// 配置集线器
app.MapSignalR();
}
}
}
在Control 里新建一个MessageAction方法,在Message视图里添加代码如下:
@{
ViewBag.title = "SignaIR聊天窗口";
}
@section scripts
{
}
//消息通知 2019年10月15日18:38:56 Dennyhui
function SignalRMessage () {
//toastr.info("向页面添加消息 ", "新消息");
var NowDateNoticeList = window.WebNotificationList;
//引用自动生成的集线器代理
var chat = $.connection.serverhub;
//定义服务器调用的客户端sendMessage来显示新消息
//此处的“sendMessage”需要和后台发送消息的方法名一致
chat.client.sendMessage = function (id, title, message, poptype) {
// do somethings
}
//集线器开始工作
$.connection.hub.start().done(function () {
chat.server.init();
});
好了,一个signalR简单的入门的例子就ok了.
在任何一个web 页面中发送的消息所有的 页面都会接收到该消息。这种应用在IM系统非常广泛常见。
当然signalR并不局限于这种B/S模式的消息推送,在C/S 同样也能应用,目前我们公司xamarin android所用的就是这个signalR实现的PC之间、PC与移动端、移动端与移动端之间的交流,使用之后会发现的确挺方便的。
有人可能感觉很郁闷了,在视图中引入 这段js有什么作用?也并有写啊。
注意!,这是虚拟目录,也就是你在OWIN Startup中注册的地址
这个路径你在项目里面是找不到的!
其实在服务器端声明的所有Hub信息,最终都会生成JavaScript输出到客户端,其实谷歌浏览器中F12 ,在Sources你就可以看到写的源代码了:
来看一下在这种B/S 模式中 signalR是如何运行的吧。首先程序开始的时候,Web页面就已经与signalR的服务建立连接。
$.connection.hub.start() 意思就是有signalR服务建立连接
.done 函数表示连接成功后为发送的按钮绑定一个单击事件
发送消息的方法:chat.server.sendMsg($('#message').val())
在ServerHub重写一个 OnConnected 方法来监控客户端的连接情况,的确程序运行的时候web页面就已经开始建立连接了,在调试的时候可以在输入中看到 "客户端连接成功!
一个简单的如何使用signalR就是这么多,用法很广泛,当然还可以进行扩展。
可以使用Quartz这个组件和Signalr搭配进行定时调度发送消息
有兴趣的朋友可以去看下如何使用Quartz来进行定时调度。
后面我也会更新一篇关于如何使用Quartz进行定时调度Job的文章。