什么是 SignalR

目前我用业余时间正在做一个博客系统,其中有个功能就是评论通知,就是假如A用户评论B用户的时候,如果B用户首页处于打开状态,那么就会提示B用户有未读消息。暂时用SignalR来实现这个功能。我也是看了两天的资料才明白怎么去使用。

关于SignalR的理论知识可以去官网或者百度,我这里只是结合自己的功能来分享下,如果有错,请原谅指出。

下载js

SignalR是需要微软提供的js,因为我的项目是前后端分离的,所以我是单独下载到一个文件夹,然后复制js到我的前端项目里。只需要signalr.js

页面加载创建连接

  1. //创建连接
    var connection = new signalR.HubConnectionBuilder().withUrl('http://127.0.0.1:5000/chatHub').build();
    //ajax执行成功执行
  $.ajax({
            success: function (response) {              
                     connection.start().then(function () {
                            connection.invoke('SetConnectionMaps', response.data.account);
                    }
                },
            });
     

首先你要了解到SignalR基本运行的原理,官网:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-3.1&tabs=visual-studio

你可以直接继承Hub这个类,我这里用的是强类型Hub<T>,我就是为了让前端和后端统一下。刚开始Hub<T>我纠结了好久,不知道怎么用,最后我手动做了下,认为它只是为了方便前端和后端统一。

如果你只是简单的继承Hub类,你就必须调用SendAsync方法,并且指定前端接收触发的方法名称“InvokeMessage”,如果你后端和前端名字对应不上,就会有问题。

  1. public class SingalrService : Hub
  2. {
  3. private ISingalrSvc _singalrSvc;
  4. public SingalrService(ISingalrSvc singalrSvc)
  5. {
  6. _singalrSvc = singalrSvc;
  7. }
  8.  
  9. public async Task SendMessageAsync(Message sendMessage)
  10. {
  11. await Clients.All.SendAsync("InvokeMessage",sendMessage);
  12. }
  13.  
  14. public void SetConnectionMaps(string account)
  15. {
  16. string connectionid = Context.ConnectionId;
  17. _singalrSvc.SetConnectionMaps(connectionid, account);
  18. }
  19. public override Task OnDisconnectedAsync(Exception exception)
  20. {
  21. _singalrSvc.Remove(Context.ConnectionId);
  22. return base.OnDisconnectedAsync(exception);
  23. }
  24. }

所以有了强类型Hub<T>,自己定义一个接口,提过方法InvokeMessage供前前端调用。

  1. /// <summary>
  2. /// 客户端js调用方法
  3. /// </summary>
  4. public interface ISingalrClient
  5. {
  6. Task InvokeMessage(Message sendMessage);
  7. }
  8. public class SingalrService : Hub<ISingalrClient>
  9. {
  10. private ISingalrSvc _singalrSvc;
  11. public SingalrService(ISingalrSvc singalrSvc)
  12. {
  13. _singalrSvc = singalrSvc;
  14. }
  15. public void SetConnectionMaps(string account)
  16. {
  17. string connectionid = Context.ConnectionId;
  18. _singalrSvc.SetConnectionMaps(connectionid, account);
  19. }
    //连接中断时执行,微软这样描述的:
    //重写 OnDisconnectedAsync 虚方法,以便在客户端断开连接时执行操作。 如果客户端故意断开连接(例如,通过调用 connection.stop()),exception 参数将 null
    //但是,如果客户端由于错误(例如网络故障)而断开连接,则 exception 参数将包含描述失败的异常
  20. public override Task OnDisconnectedAsync(Exception exception)
  21. {
  22. _singalrSvc.Remove(Context.ConnectionId);
  23. return base.OnDisconnectedAsync(exception);
  24. }
  25. }

这个时候一个用户打开了首页,然后首页有个js方法来初始化连接,同一个页面内的connectionid是一样的,每次刷新或新打开一个窗口的新页面的connectionid是不一样的,并且你刷新页面或者关掉会认为是连接中断,会执行OnDisconnectedAsync方法,这个方法时SingalR自带的,它是个虚方法,你也可以重写,就像我一样。我这里的代码逻辑是将连接id和当前登录人作为键值对存入内存,然后用户关掉页面就会执行OnDisconnectedAsync方法,将相关的coonectionid从内存删掉:

  1. layui.use(['element', 'layer'], function () {
    var element = layui.element;
  2. element.render('nav');
  3. initLoad();
    //初始化连接,每个页面的connection的connectionid是一样的,但是每次创建的不一样
  4. var connection = new signalR.HubConnectionBuilder().withUrl('http://127.0.0.1:5000/chatHub').build();
    //绑定后台触发的方法,前面已经讲过了,具体业务还没实现,
  5. connection.on('InvokeMessage', (reviceMessage) => {
  6. var v = reviceMessage;
  7. });
  8. $.ajax({
  9. url: url + 'user/userInfo',
  10. type: 'get',
  11. dataType: 'json',
  12. beforeSend: function (xhr) {
  13. doBeforeSend(xhr);
  14. },
  15. success: function (response) {
  16. if (response.code == '1') {
  17. $("#nologin").show();
  18. $("#user").hide();
  19. }
  20. else {
  21. $("#nologin").hide();
  22. $("#user").show();
  23. $("#photo").attr('src', response.data.headPhoto);
    //连接开始
  24. connection.start().then(function () {
    //调用后台方法,不是api接口,将当前登录人账号传过去
  25. connection.invoke('SetConnectionMaps', response.data.account);
  26. })
  27. }
  28. },
  29. complete: function (xhr) {
  30. doComplete(xhr);
  31. },
  32. });
  33. });

这个时候连接已经创建完成,并且用户并没有关闭首页,连接一直处于连接状态。这个时候另一个用户打开了一篇文章详情,并且对它评论提交内容后,我让它触发了一个连接SingalR的事件,

  1. form.on('submit(review)', function (data) {
  2. loading = layer.load(2);
  3. var commentModel = {
  4. 'Content': data.field.desc,
  5. }
  6. $.ajax({
  7. url: url + 'article/review/' + id,
  8. contentType: 'application/json; charset=utf-8',
  9. type: 'post',
  10. datatype: 'json',
  11. data: JSON.stringify(commentModel),
  12. beforeSend: function (xhr) {
  13. doBeforeSend(xhr);
  14. },
  15. success: function (response) {
  16. if (response.code == 0) {
  17. //另一个用户创建了连接
  18. var connection = new signalR.HubConnectionBuilder().withUrl('http://127.0.0.1:5000/chatHub').build();
  19. connection.start().then(function () {
  20. var apiRoute=url+'Singalr/admin';//admin是我设置死的,实际应该是自己判断,会调用下面的api,[Route("api/[controller]")],SingalR也是支持api调用的
  21. var token=localStorage.getItem('token');
  22. fetch(apiRoute,{
  23. method:'get',
  24. headers:{
  25. 'Authorization':'Bearer ' + token
  26. }
  27. })
  28. event.preventDefault();
  29. })
  30. layer.close(loading);
  31. } else {
  32. layer.close(loading);
  33. layer.msg("评论失败", {
  34. icon: 5
  35. });
  36. }
  37. },
  38. complete: function (xhr) {
  39. doComplete(xhr);
  40. },
  41. })
  1. [ApiController]
  2. public class SingalrController : ControllerBase
  3. {
  4. private IHubContext<SingalrService, ISingalrClient> _hubContext;
  5. private ISingalrSvc _singalrSvc;
  6. public SingalrController(IHubContext<SingalrService, ISingalrClient> hubContext, ISingalrSvc singalrSvc)
  7. {
  8. _hubContext = hubContext;
  9. _singalrSvc = singalrSvc;
  10. }
  11. /// <summary>
  12. /// 查询未处理数量
  13. /// </summary>
  14. /// <param name="account"></param>
  15. /// <returns></returns>
  16. [HttpGet("{account}")]
  17. public async Task NewsCount(string account)
  18. {
  19. Message sendMessage = new Message();
  20. sendMessage.Data = "11";
    //刚已经讲了,用户加载首页的时候已经把connectionid和account存入到了内存里面,现在再取用户相关的connectionID,如果直接调用Clinets.ALL就是给所有客户端发送消息
  21. IReadOnlyList<string> connectionIds = (IReadOnlyList<string>)_singalrSvc.GetConnectionIds(account);
  22. await _hubContext.Clients.Clients(connectionIds).InvokeMessage(sendMessage);
  23. }
  24. }

这个时候调用了这个api执行了里面的_hubContext.Clients.Clients(connectionIds).InvokeMessage(sendMessage),connectionIds是根据业务逻辑所判断的触发的那些客户端;然后前端会根据方法名响应对应的js代码,如下

  1. layui.use(['element', 'layer'], function () {
  2. var element = layui.element;
  3. element.render('nav');
  4. initLoad();
  5. var connection = new signalR.HubConnectionBuilder().withUrl('http://127.0.0.1:5000/chatHub').build();
  6.  
  7. //我认为是一个用来侦听服务端方法的js
  8. connection.on('InvokeMessage', (reviceMessage) => {
  9. var v = reviceMessage;
    //响应后端方法成功后,就开始自己的业务逻辑
  10. });
  11. $.ajax({
  12. url: url + 'user/userInfo',
  13. type: 'get',
  14. dataType: 'json',
  15. beforeSend: function (xhr) {
  16. doBeforeSend(xhr);
  17. },
  18. success: function (response) {
  19. if (response.code == '1') {
  20. $("#nologin").show();
  21. $("#user").hide();
  22. }
  23. else {
  24. $("#nologin").hide();
  25. $("#user").show();
  26. $("#photo").attr('src', response.data.headPhoto);
  27. connection.start().then(function () {
  28. connection.invoke('SetConnectionMaps', response.data.account);
  29. })
  30. }
  31. },
  32. complete: function (xhr) {
  33. doComplete(xhr);
  34. },
  35. });
  36. });

  

游戏也能赚钱?如果你热爱游戏,并且想通过游戏赢得零花钱,5173是个不错的选择  http://www.5173.com/?recommenduserid=US15061749098191-04F6

ASP.NET Core SignalR :学习消息通讯,实现一个消息通知的更多相关文章

  1. ASP.NET Core SignalR中的流式传输

    什么是流式传输? 流式传输是这一种以稳定持续流的形式传输数据的技术. 流式传输的使用场景 有些场景中,服务器返回的数据量较大,等待时间较长,客户端不得不等待服务器返回所有数据后,再进行相应的操作.这时 ...

  2. Asp.Net Core SignalR 用泛型Hub优雅的调用前端方法及传参

    继续学习 最近一直在使用Asp.Net Core SignalR(下面成SignalR Core)为小程序提供websocket支持,前端时间也发了一个学习笔记,在使用过程中稍微看了下它的源码,不得不 ...

  3. Asp.Net Core SignalR 与微信小程序交互笔记

    什么是Asp.Net Core SignalR Asp.Net Core SignalR 是微软开发的一套基于Asp.Net Core的与Web进行实时交互的类库,它使我们的应用能够实时的把数据推送给 ...

  4. ASP.NET Core SignalR

    ASP.NET Core SignalR 是微软开发的一套基于ASP.NET Core的与Web进行实时交互的类库,它使我们的应用能够实时的把数据推送给Web客户端. 功能 自动管理连接 允许同时广播 ...

  5. Asp.Net Core WebApi学习笔记(四)-- Middleware

    Asp.Net Core WebApi学习笔记(四)-- Middleware 本文记录了Asp.Net管道模型和Asp.Net Core的Middleware模型的对比,并在上一篇的基础上增加Mid ...

  6. ASP.NET Core SignalR:基础概述

    一.简介 ASP.NET Core SignalR 是一个开源代码库,它简化了向应用添加实时 Web 功能的过程. 实时 Web 功能使服务器端代码能够即时将内容推送到客户端. SignalR 的适用 ...

  7. 使用websocket连接(对接)asp.net core signalr

    使用通用websocket连接asp.net core signalr 一.背景介绍 signalr的功能很强大,可以为我们实现websocket服务端节省不少的时间.但是可能由于不同的环境,我们在对 ...

  8. ASP.NET CORE使用WebUploader对大文件分片上传,并通过ASP.NET CORE SignalR实时反馈后台处理进度给前端展示

    本次,我们来实现一个单个大文件上传,并且把后台对上传文件的处理进度通过ASP.NET CORE SignalR反馈给前端展示,比如上传一个大的zip压缩包文件,后台进行解压缩,并且对压缩包中的文件进行 ...

  9. 学习ASP.NET Core Blazor编程系列二——第一个Blazor应用程序(中)

    学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 四.创建一个Blazor应用程序 1. 第一种创 ...

  10. [asp.net core]SignalR一个例子

    摘要 在一个后台管理的页面想实时监控一些操作的数据,想到用signalR. 一个例子 asp.net core+signalR 使用Nuget安装包:Microsoft.AspNetCore.Sign ...

随机推荐

  1. 修改tomcat默认使用的jdk版本

    1.windows平台 在csetclasspath.bat文件开头加上如下两句(指定JDK): set JAVA_HOME=C:\Program Files\Java\jdk1.7.0_79  se ...

  2. Pandas 转换连接

    # 导入相关库 import numpy as np import pandas as pd 拼接 有两个 DataFrame,都存储了用户的一些信息,现在要拼接起来,组成一个 DataFrame. ...

  3. [考试反思]1109csp-s模拟测试107:低能

    诶一看这不是水题AK场吗?然后80分钟就拿到了285分. 然后,对拍?还是卡T2常数?还是想T2正解? 于是上述三项我依次进行了. 前两项让我的分数丝毫不变但是吃掉了我一个多小时的时间. 卡常卡的也不 ...

  4. re模块的基本使用

    目录 re模块 常用元字符 特殊构造 贪婪模式 非贪婪模式 re的常用函数 re模块补充 关于re模块必须知道的知识点 re模块 re模块 , 即正则表达式 , 本身是一种小型的.高度专业化的编程语言 ...

  5. 极光推送(JPush)开篇

    Date:2019-11-11 读前思考: 极光推送是什么? 极光推送是能做什么?有什么优势? 怎么根据业务需求来实现极光推送服务呢? 简介 极光推送(JPush)是独立的第三方云推送平台,致力于为全 ...

  6. Comparable接口的实现和使用

    1.什么是Comparable接口 此接口强行对实现它的每个类的对象进行整体排序.此排序被称为该类的自然排序 ,类的 compareTo 方法被称为它的自然比较方法 .实现此接口的对象列表(和数组)可 ...

  7. Linux软件包管理和磁盘管理实践

    一.自建yum仓库,分别为网络源和本地源 本地yum仓库的搭建就是以下三个步骤: 创建仓库目录结构 上传相应的包到目录下,或者直接挂载光盘也行,如果挂载光盘,第三步就可以省略,因为光盘默认里有repo ...

  8. Python 基础之socket编程(一)

    Python 基础之socket编程(一) 可以进行通信玩儿了,感觉不错不错,网络通信就像打电话,我说一句你听一句之后,你再说一句,我听一句,就这样.....下去了.不扯淡了,来来来,看看今天都搞了点 ...

  9. 【转载】常见十大经典排序算法及C语言实现【附动图图解】

    原文链接:https://www.cnblogs.com/onepixel/p/7674659.html 注意: 原文中的算法实现都是基于JS,本文全部修改为C实现,并且统一排序接口,另外增加了一些描 ...

  10. 【笔记】nginx部署静态网站

    安装nginx 本地到官网下载,然后把压缩包传到服务器上 安装三个依赖 apt-get install libpcre3 libpcre3-dev apt-get install zlib1g-dev ...