|
官网文档:https://learn.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-6.0&tabs=visual-studio
SignalR开源代码:https://github.com/signalr
很多小伙伴问:在前后端分离项目中,后端是.NET Core前端是Vue如何使用SignalR?在前后端不分离项目中,.NET Framework MVC项目中又如何使用SignalR技术呢?那就来看看下面这篇文章吧!本文主要介绍SignalR在实际项目中的应用,以及.NET Framework和.NET Core中如何去使用SignalR。
一、SignalR介绍
1.1-SignalR介绍
ASP.NET Core SignalR是一个开放源代码库,可用于简化向应用添加实时Web功能,实时Web功能使服务器端代码能够将内容推送到客户端。
1.2-SignalR的应用
- 需要从服务器进行高频更新的应用:包括游戏、社交网络、投票、拍卖、地图和GPS引用。
- 仪表盘和监视应用:包括公司仪表板、即时销售更新或旅行报警
- 协作应用:包括白板应用和团队会议软件。
- 通知应用:社交网络、电子邮件、聊天、游戏、旅行报警和其他应用都需要使用的通知。
二、.NET Framework使用SignalR
参考文献:
Owin介绍:https://www.cnblogs.com/Pinapple/p/6721361.html
Owin相关案例:https://blog.csdn.net/bifan546/article/details/77098896/
2.1-服务端(.NET Framework MVC)
(1)选择要使用Signalr的项目,点击【管理NuGet程序包】。
(2)搜索【SignalR】包,找到这个后然后点击下载。
会自动安装四个,注意他们之间有依赖关系:
(3).NET Framework平台需要添加Owin相关的包。
OWIN 是一种定义 Web 服务器和应用程序组件之间的交互的规范 。这一规范的目的是发展一个广阔且充满活力的、基于 Microsoft .NET Framework 的 Web 服务器和应用程序组件生态系统。
Microsoft.Owin.Hosting
Microsoft.Owin.Cors
Microsoft.Owin.Host.HttpListener
(4)在Web项目(要使用的Signal)中创建一个【Startup.cs】文件。- using JiCai.Admin.Hubs;
- using Microsoft.Owin;
- using Owin;
- [assembly: OwinStartup(typeof(JiCai.Admin.Startup))]
- namespace JiCai.Admin
- {
- public class Startup
- {
- /// <summary>
- /// 应用程序配置
- /// </summary>
- /// <param name="app"></param>
- public void Configuration(IAppBuilder app)
- {
- //启用SignalR
- app.MapSignalR();
- //绑定多个Hub
- app.MapSignalR<DemoHub>("/demoHub");
- }
- }
- }
复制代码 例如:
(5)可以创建一个【Hubs】文件夹,专门放置Hub相关文件。[西瓜程序猿]这边是创建一个Hub文件,名为【DemoHub.cs】。- using Fenqibao.DTO;
- using JiCai.Admin.Hubs.ConectionOperate;
- using JiCai.Admin.Hubs.Models;
- using log4net;
- using Microsoft.AspNet.SignalR;
- using Microsoft.AspNet.SignalR.Json;
- using Newtonsoft.Json;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- namespace JiCai.Admin.Hubs
- {
- /// <summary>
- /// 报表管理-总表Hub
- /// </summary>
- public class SummaryTableHub : PersistentConnection
- {
- public readonly BaseService _base = new BaseService();
- private readonly ILog logger = LogManager.GetLogger(typeof(SummaryTableHub));
- private ConnectionManagement summaryTableCon = new ConnectionManagement();
- public CookieUserData LoginUserData
- {
- get
- {
- IOperator oper = ContainerManager.Resolve<IOperator>();
- LoginUser loginUser = oper as LoginUser;
- if (loginUser != null && loginUser.UserData != null)
- {
- return loginUser.UserData;
- }
- return null;
- }
- }
- /// <summary>
- /// 连接成功后调用
- /// </summary>
- /// <param name="request"></param>
- /// <param name="connectionId"></param>
- /// <returns></returns>
- protected override Task OnConnected(IRequest request, string connectionId)
- {
- //获得SignalR的连接id
- var connid = connectionId;
- //获得用户id
- var userid = LoginUserData.Id.ToString();
- Console.Write($"【{connid}】:已建立连接!");
- //判断一下用户是不是已经链接了
- var checkUserConn = summaryTableCon.IsConn(connid, userid);
- if (!checkUserConn)
- {
- //添加一个新的连接
- summaryTableCon.AddConnInfo(new SignalRConn()
- {
- UserId = userid,
- ConnectionId = connid
- });
- }
- //更新连接
- else
- {
- summaryTableCon.UpdateConnInfo(userid, connid);
- }
- return Connection.Send(connectionId, $"【用户:{connectionId}】真正连接成功!");
- //return base.OnConnected(request, connectionId);
- }
- /// <summary>
- /// 接收到请求的时候调用
- /// </summary>
- /// <param name="request"></param>
- /// <param name="connectionId"></param>
- /// <param name="data"></param>
- /// <returns></returns>
- protected override async Task OnReceived(IRequest request, string connectionId, string data)
- {
- //获得用户id
- var userid = LoginUserData.Id.ToString();
- await Task.Factory.StartNew(async () =>
- {
- while (true)
- {
- var list = GetSummaryTableList(userid);
- string json_jieshou_mes = "";
- if (list != null && list.Count > 0)
- {
- json_jieshou_mes = JsonConvert.SerializeObject(list);
- }
- await Connection.Send(connectionId, json_jieshou_mes);
- //每5秒同步一次
- await Task.Delay(5000);
- }
- }, TaskCreationOptions.LongRunning);
- //return base.OnReceived(request, connectionId, data);
- }
- /// <summary>
- /// 连接中断的时候调用
- /// </summary>
- /// <param name="request"></param>
- /// <param name="connectionId"></param>
- /// <param name="stopCalled"></param>
- /// <returns></returns>
- protected override Task OnDisconnected(IRequest request, string connectionId, bool stopCalled)
- {
- Console.Write($"【{connectionId}】:已断开连接!");
- //获得SignalR的连接id
- var connid = connectionId;
- //关闭连接
- summaryTableCon.DelConnInfo(connid);
- return base.OnDisconnected(request, connectionId, stopCalled);
- }
- /// <summary>
- /// 连接超时重新连接的时候调用
- /// </summary>
- /// <param name="request"></param>
- /// <param name="connectionId"></param>
- /// <returns></returns>
- protected override Task OnReconnected(IRequest request, string connectionId)
- {
- return base.OnReconnected(request, connectionId);
- }
- /// <summary>
- /// 查询数据
- /// </summary>
- /// <param name="userId"></param>
- /// <returns></returns>
- private List<SummaryTableDataModel> GetSummaryTableList(string userId)
- {
- var result = _base.Query<SummaryTableDataModel>($@"
- select * from demo-data
- ;
- ").ToList();
- return result;
- }
- }
- }
复制代码 (6)在Hubs/ConectionOperate文件夹中,[西瓜程序猿]这边创建【ConnectionManagement】文件,用来管理所有连接。- using System.Collections.Generic;
- using System.Linq;
- namespace JiCai.Admin.Hubs.ConectionOperate
- {
- /// <summary>
- /// 连接管理
- /// </summary>
- public class ConnectionManagement
- {
- /// <summary>
- /// 用户连接集合
- /// </summary>
- public static List<SignalRConn> SignalRConns { get; set; } = new List<SignalRConn>();
- /// <summary>
- /// 添加连接
- /// </summary>
- /// <param name="conn"></param>
- public void AddConnInfo(SignalRConn conn)
- {
- SignalRConns.Add(conn);
- }
- /// <summary>
- /// 删除连接
- /// </summary>
- /// <param name="connid"></param>
- public void DelConnInfo(string connid)
- {
- var signalRConns = SignalRConns.FirstOrDefault(u => u.ConnectionId == connid);
- if (signalRConns != null)
- {
- SignalRConns.Remove(signalRConns);
- }
- }
- /// <summary>
- /// 更新链接(老的链接不起作用了)
- /// 场景:客户端重连了,userid没变,但是connid变了
- /// </summary>
- /// <param name="userId">用户id</param>
- /// <param name="newConnsId">新的链接id</param>
- public void UpdateConnInfo(string userId, string newConnsId)
- {
- var signalRConns = SignalRConns.FirstOrDefault(u => u.UserId.ToLower() == userId.ToLower());
- if (signalRConns != null)
- {
- signalRConns.ConnectionId = newConnsId;
- }
- }
- /// <summary>
- /// 判断用户是否已经链接
- /// </summary>
- /// <param name="connid">连接id</param>
- /// <param name="userid">用户id</param>
- /// <returns></returns>
- public bool IsConn(string connid,string userid)
- {
- var userConn = SignalRConns.FirstOrDefault(u => u.ConnectionId.ToLower() == connid.ToLower() && u.UserId.ToLower() == userid.ToLower());
- return userConn == null ? false : true;
- }
- }
- }
复制代码 (7)在Hubs/ConectionOperate文件夹中,创建【SignalRConn.cs】文件用来作为SignalR和系统用户的连接实体。- namespace JiCai.Admin.Hubs.ConectionOperate
- {
- /// <summary>
- /// 连接
- /// </summary>
- public class SignalRConn
- {
- /// <summary>
- /// 系统用户id
- /// </summary>
- public string UserId { get; set; }
- /// <summary>
- /// SignleR链接Id(每次链接SignalR都会分配一个id)
- /// </summary>
- public string ConnectionId { get; set; }
- }
- }
复制代码 2.2-客户端(JS)
(1)下载相关jq/signalr相关包,分别是【jquery.signalR-2.4.3.js】和【jquery-1.6.4.min.js】。可以访问下载(如果失效了,请联系我[西瓜程序猿])。
下载地址(编码:yRLCRp81):https://yongteng.lanzoub.com/iXDlu1631ugd
密码:44x5
文件截图:
(2)创建一个js文件【data_list_table_hub.js】,用来连接signalR。- // 连接服务
- var connection = $.connection("/summary_table_hub");
- // 建立链接
- connection.start(function () {
- //连接成功
- console.log("西瓜程序猿-【" + new Date().toLocaleString() +"】连接成功!");
- //发送消息
- connection.send("给我数据吧");
- });
- // 连接断开
- connection.disconnected(function () {
- console.log("西瓜程序猿-【" + new Date().toLocaleString() +"】连接断开!");
- });
- // 接收服务器发来的消息
- connection.received(function (data) {
- console.log("西瓜程序猿-【" + new Date().toLocaleString() +"】接收服务器发来的消息:");
- console.log(data);
- //显示数据
- if (data != "" && checkJson(data)) {
- var obj = JSON.parse(data);
- var html_box = "";
- for (var i = 0; i < obj.length; i++) {
- html_box += `<tr>
- <td>`+obj[i].project_name+`</td>
- <td>`+ obj[i].zuori_sum+`</td>
- <td>`+ obj[i].jinri_sum+`</td>
- <td>`+ obj[i].qunian_sum+`</td>
- <td>`+ obj[i].jinnian_sum+`</td>
- <td>`+ obj[i].sum+`</td>
- <td>`+ obj[i].yikaipiao_sum+`</td>
- <td>`+ obj[i].weikaipiao_sum +`</td>
- <td>`+ obj[i].yishoupiao_sum +`</td>
- <td>`+ obj[i].weishoupiao_sum +`</td>
- <td>`+ obj[i].kehu_yinghuikuan_sum+`</td>
- <td>`+ obj[i].kehu_yihuikuan_sum+`</td>
- <td>`+ obj[i].kehu_weihuikuan_sum +`</td>
- <td>`+ obj[i].fuwu_yingfukuan_sum+`</td>
- <td>`+ obj[i].fuwu_yifukuan_sum+`</td>
- <td>`+ obj[i].fuwu_weifukuan_sum+`</td>
- </tr>`
- }
- $("#last_async_date").text(new Date().toLocaleString());
- $("#table_body").html(html_box);
- }
- });
- //判断是不是json字符串
- function checkJson(str) {
- if (typeof str == 'string') {
- try {
- var obj = JSON.parse(str);
- // 等于这个条件说明就是JSON字符串 会返回true
- if (typeof obj == 'object' && obj) {
- return true;
- } else {
- //不是就返回false
- return false;
- }
- } catch (e) {
- return false;
- }
- }
- return false;
- }
复制代码 (3)创建要展示的文件,我这边是用MVC模式,所有前台文件是cshtml。- @{
- ViewBag.Title = "西瓜程序猿-明细表";
- }
- @section styles{
-
- }
- @section scripts{
-
-
-
- }
-
-
-
-
- 报表最新同步时间:
-
-
- <table >
- <colgroup>
- <col>
- <col>
- <col>
- <col>
- <col>
- <col>
- <col>
- <col>
- <col>
- <col>
- <col>
- <col>
- <col>
- </colgroup>
- <thead>
- <tr>
- <th colspan="2" >项目信息</th>
- <th colspan="5" >销售情况</th>
- <th colspan="6" >款项情况</th>
- </tr>
- <tr>
- <th >项目名称</th>
- <th >服务商名称</th>
- <th >昨天订单总额</th>
- <th >今天订单总额</th>
- <th >去年订单总额</th>
- <th >今年订单总额</th>
- <th >订单总额</th>
- <th >客户应回款总额</th>
- <th >客户已回款总额</th>
- <th >客户未回款总额</th>
- <th >服务商应付款总额</th>
- <th >服务商已付款总额</th>
- <th >服务商未付款总额</th>
- </tr>
- </thead>
- <tbody id="table_body">
- </tbody>
- </table>
-
-
复制代码 (4)效果展示:
三、.NET Core WebAPI使用SignalR
场景:项目中需要服务端主动向客户端发送通知消息,后端是使用.NETCore实现的,前端是使用Vue3全家桶项目,前后端分离模式。本次主要讲使用SignalR如何来实现的。
3.1-服务端(.NET Core WebAPI)
1、右击项目,点击【管理NuGet程序包】安装SignalR。
2、搜索【SignalR】,点击【安装】。
3、如果是.NET6以前的版本,在【Startup.cs】中配置:
如果是.NET6以后得版本,在【Program.cs】配置:- var builder = WebApplication.CreateBuilder(args);
- //添加SignalR服务
- builder.Services.AddSignalR();
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapControllerRoute(
- name: "default",
- pattern: "{controller=Home}/{action=Index}/{id?}"
- );
- //添加SignalR端点
- endpoints.MapHub<ServerMonitorHub>("/serverMonitorHub");
- });
复制代码
4、创建SignalR中心
中心是一个类,用于处理客户端服务器通信的高级管道。在SignalR_Demo项目文件夹中,创建Hubs文件夹。在Hubs文件夹中,使用已下代码创建ChatHub类。
- public class ChatHub:Hub
- {
- /// <summary>
- /// 发送消息
- /// </summary>
- /// <param name="user">用户名</param>
- /// <param name="message">发送信息</param>
- /// <returns></returns>
- public async Task SendMessage(string user,string message)
- {
- await Clients.All.SendAsync("ReceiveMessage", user, message);
- }
- }
复制代码 3.2-客户端(Vue3+Vite+TS)
(1)安装SugbalR- npm install @latelier/vue-signalr
复制代码 版本截图:
(2)然后新建一个文件,用来封装业务逻辑相关代码。[西瓜程序猿]是在【src/utils】目录下,创建了一个名为【signalr.ts】的文件,也可以是js文件,根据自己项目的需要去新建。
代码:- import * as signalR from '@microsoft/signalr';
- //如果需要身份验证
- //.withUrl('/messageHub', {accessTokenFactory: () => sessionStorage.getItem('token')})
- let connection;
- // 建立连接
- async function start(url) {
- try {
- connection = new signalR.HubConnectionBuilder()
- .withUrl(url)//跨域需要使用绝对地址
- .configureLogging(signalR.LogLevel.Information)
- .withAutomaticReconnect() // 设置自动重连机制
- .build();
- } catch(err) {
- console.log(err);
- setTimeout(start, 10000);//错误重连
- }
- }
- // 开始signalr连接
- const connect = async (url) => {
- await start(url);
- console.log(`【西瓜程序猿-${new Date().toLocaleString()}:SignalR已连接成功!`);
- };
- // 调用服务端方法
- async function send(methodName, param){
- try {
- await connection.invoke(methodName, param);
- } catch (err) {
- console.error(err);
- }
- }
- //断开连接
- const disconnect = async ()=>{
- await connection.stop();
- console.log(`【西瓜程序猿-${new Date().toLocaleString()}:SignalR已断开连接!`);
- };
- export {
- connection,
- connect,
- send,
- disconnect
- };
复制代码 (3)然后再页面进行使用。[西瓜程序猿]这里以Echarts图表展示为例子,首先先安装Echarts包。
npm install echarts --save
版本截图:
(4)然后再页面写入如下代码,具体页面样式根据需要进行修改调整哦。(5)效果展示:
原文链接:https://www.cnblogs.com/kimiliucn/p/17648543.html
来源:https://www.cnblogs.com/kimiliucn/archive/2023/08/22/17648543.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|