北京中科白瘕风 http://www.bdfyy999.com/bdf/
什么是SignalRASP.NETCore
ASP.NETCoreSignalR是一种开放源代码库,可简化将实时web功能添加到应用程序的功能。实时web功能使服务器端代码可以立即将内容推送到客户端。
SignalRASP.NETCore可以做什么
?需要从服务器进行高频率更新的应用。示例包括游戏、社交网络、投票、拍卖、地图和GPS应用。?仪表板和监视应用。示例包括公司仪表板、即时销售更新或旅行警报。?协作应用。协作应用的示例包括白板应用和团队会议软件。?需要通知的应用。社交网络、电子邮件、聊天、游戏、旅行警报和很多其他应用都需使用通知。
SignalRASP.NETCore特色
?自动处理连接管理。?可将消息同时发送到所有连接的客户端。?可向特定客户端或客户端组发送消息。?可缩放以处理不断增加的流量。?SignalR采用rpc来进行客户端与服务器端之间的通信。?SignalR会自动选择服务器和客户端的最佳传输方法(WebSockets、Server-Sent事件、长轮询)SignalR可以根据当前浏览器所支持的协议来选择最优的连接方式,从而可以让我们把更多的精力放在业务上而不是底层传输技术上。
哪些浏览器支持SignalRASP.NETCore
AppleSafari(包含IOS端)、GoogleChrome(包括Android端)、MicrosoftEdge、MozillaFirefox等主流浏览器都支持SignalRASP.NETCore。
本次我们将实现一个通过SignalR来简单实现一个后台实时推送数据给Echarts来展示图表的功能
首先我们新建一个ASP.NETCore3.1的web应用
随后我们引用SignalRASP.NETCore、Jquery和Echarts的客户端库
在项目中我们新建以下目录
Class、HubInterface、Hubs
接着我们在Pages目录下新建如下目录
echarts
在Shared目录中新建一个Razor布局页(_LayoutEcharts.cshtml)
在echarts目录中新建一个Razor页面(Index.cshtml)
在Class目录中新建一个类(ClientMessageModel.cs)
在HubInterface目录中新建一个接口(IChatClient.cs)
在Hub目录中新建一个类(ChatHub.cs)
我们先实现后台逻辑代码,随后在编写前端交互代码。
在IChatClient.cs中,我们主要是定义统一的服务端调用客户端方法的统一方法名(防止每次都要手动输入调用方法是出现失误而导致调用失败的低级错误)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
namespacesignalr.HubInterface
{
publicinterfaceIChatClient
{
///summary
///客户端接收数据触发函数名
////summary
///paramname="clientMessageModel"消息实体类/param
///returns/returns
TaskReceiveMessage(ClientMessageModelclientMessageModel);
///summary
///Echart接收数据触发函数名
////summary
///paramname="data"JSON格式的可以被Echarts识别的data数据/param
///returns/returns
TaskEchartsMessage(Arraydata);
///summary
///客户端获取自己登录后的UID
////summary
///paramname="clientMessageModel"消息实体类/param
///returns/returns
TaskGetMyId(ClientMessageModelclientMessageModel);
}
}
ClientMessageModel.cs中,我们主要定义的是序列化后的交互用的实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespacesignalr.Class
{
///summary
///服务端发送给客户端的信息
////summary
[Serializable]
publicclassClientMessageModel
{
///summary
///接收用户编号
////summary
publicstringUserId{get;set;}
///summary
///组编号
////summary
publicstringGroupName{get;set;}
///summary
///发送的内容
////summary
publicstringContext{get;set;}
}
}
在ChatHub.cs中,主要是实现SignalR集线器的核心功能,用来处理客户端==服务器交互代码。在这里我们继承了HubT的方法,集成了我们定义的IChatClient接口,从而就可以在方法中直接调用接口名称来和客户端交互。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespacesignalr.Hubs
{
publicclassChatHub:HubIChatClient
{
publicoverrideasyncTaskOnConnectedAsync()
{
varuser=Context.ConnectionId;
awaitClients.Client(user).GetMyId(newClientMessageModel{UserId=user,Context="回来了{DateTime.Now:yyyy-MM:ddHH:mm:ss}"});
awaitClients.AllExcept(user).ReceiveMessage(newClientMessageModel{UserId=user,Context="进来了{DateTime.Now:yyyy-MM:ddHH:mm:ss}"});
awaitbase.OnConnectedAsync();
}
publicoverrideasyncTaskOnDisconnectedAsync(Exceptionexception)
{
varuser=Context.ConnectionId;
awaitClients.All.ReceiveMessage(newClientMessageModel{UserId=user,Context="{user}离开了{DateTime.Now:yyyy-MM:ddHH:mm:ss}"});
awaitbase.OnDisconnectedAsync(exception);
}
}
}
我们重写了Hub的OnConnectedAsync方法,当有客户端连接进来的时候,我们给当前客户端发送一条“回来了”的内容,同时给所有在线的客户端发送一条“进来了”的通知,内容中会带上本次连接所分配给动态Guid编号。(类似与通知大家谁谁上线了)
在OnDisconnectedAsync方法中,当客户端断开连接的时候,会给所有在线客户端发送一条带有离线客户端的Guid的离开消息。(类似通知大家谁谁谁离开了)
在Startup.cs中,我们做以下设置(注入SignalR和注册Hub),同时先把在DEBUG模式下的XSRF禁用,否则访问接口会提示错误
1
2
3
4
5
6
7
8
9
10
11
12
13
publicvoidConfigureServices(IServiceCollectionservices)
{
services.AddSignalR();
services.AddRazorPages()
#ifDEBUG
//Debug下禁用XSRF防护,方便调试
.AddRazorPagesOptions(o=
{
o.Conventions.ConfigureFilter(newIgnoreAntiforgeryTokenAttribute());
})
#endif
;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints=
{
endpoints.MapRazorPages();
endpoints.MapHubChatHub("/chathub");//注册hub
});
}
以上服务端的基架功能就搭建好了,下面我们会来实现后台推送数据给前台Echart的功能。
在_LayoutEcharts.cshtml布局页中,我们实现引用Jquery和Echarts的JS文件,同时编写一个请求后台接口的方法,调用这个方法后,后台就会主动推送多次数据给前台。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
!DOCTYPEhtml
html
head
metacharset="utf-8"
metaname="viewport"content="width=device-width"/
scriptsrc="~/lib/echarts/dist/echarts.min.js"/script
scriptsrc="~/lib/jquery/dist/jquery.js"/script
title
ViewBag.Title/titlescript
functionTest(){
varchartDom=document.getElementById(main);
varmyChart=window.echarts.init(chartDom);
.ajax({
url:/echarts,
type:POST,
dateType:json,
data:{user:user},
beforeSend:function(XHR){
console.log(Iam+user);
myChart.showLoading({
text:加载中。。。,
effect:whirling
});
},
success:function(data){
varoption={
series:[{
data:data.data
}]
};
myChart.setOption(option);
},
error:function(XMLHttpRequest,textStatus,errorThrown){
alert(errorThrown);
},