ASP.NET MVC4使用SignalR实现实时通讯

本文介绍在ASP.NET MVC框架中如何使用SignalR进行实时通讯

1.如何在Web中实现实时通讯

实时通讯

例如“消息提示”、“web聊天室”等。由于web浏览器中使用的是http协议(大部分请求)进行通讯,http被称为是无状态,每次http请求和应答都是通过建立tcp连接,发送数据反馈应答,关闭tcp连接。而且必须是客户端先请求服务器端,服务器端再反馈给客户端消息。并不能实现服务器端主动给客户端推送消息的功能。

实时通讯的传统实现方法

1.刷新整个页面。这种方法最为原始,页面中设置一个时间触发器,指定时间周期执行页面刷新操作。即隔一定时间向服务器请求一次最新的数据。

2.刷新部分页面。为了避免全部页面的刷新,可通过ajax动态的刷新部分页面。

3.轮询(现阶段较好的实现方式)。通过ajax向服务器询问是否有新的数据,如果有新的数据,则动态的刷新当前页面的指定内容。

SignalR方式:

SignalR是一个实现实时通讯的完整解决方案,包含服务器端和客户端(浏览器端)的全部内容。

它会根据客户端的不同而动态的选择低层实现方案,如果浏览器支持html5,signalr就会选择WebSocket方式;如果不支持,就会选择Comet方式。实际上都是尝试在服务器端和客户端(浏览器端)建立持久连接。

关于SignalR的原理这里就不再敖述,具体内容请参见官方介绍:http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/introduction-to-signalr

实现原理图:

即:用户A在浏览器中的某个操作,使得用户A的浏览器端调用了服务器端的某个函数MyServerFunc(),同时传过来想将消息发送给谁的用户Id。服务器端再根据这个Id号,调用这个Id对应的用户的浏览器端定义个某个函数:myClientFunc()。从而实现了用户A实时发送消息给用户B。

2.如何在ASP.NET MVC框架中使用SignalR

微软的官方网站上介绍了两种搭配方案:

1.ASP.NET MVC4搭配SignalR1.x

2.ASP.NET MVC5搭配SignalR2

(按照asp.net mvc框架和signalr的发布时间顺序,他们应该就是这样的搭配。但是笔者自己在项目开发中先选择了MVC4框架,但是后来在选择signalr时选择了最新版本2.0.3。之前也是由于直接安装的最新版本,后来发现项目中确实需要使用signalr2.x版本,后面会阐述为什么需要使用2.x版本)

所以,本文笔者的项目中的搭配方案为:ASP.NET MVC4 和 SignalR2.0.3

如果读者中也有类似的需求,或者原来使用的是signalr1.x现在需要迁移到signalr2.x的,可以参考微软的一篇文档,介绍如何从signalr1.x迁移到signalr2

http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/upgrading-signalr-1x-projects-to-20

如何在项目中加入SignalR:

1.使用Nuget程序包管理工具引入signalr

Visual Studio2012中依次点击:项目->管理Nuget程序包。搜索signalr,点击安装即可。(默认为最新版本)

或者

命令行方式:工具->库程序包管理器->程序包管理器控制台,输入:install-package Microsoft.AspNet.SignalR

安装完成以后可以再scripts文件夹中看到新增加的文件:jquery.signalR-2.0.3.js等

服务器端:

2.创建自己的hub类(如果想实现signalr的功能,服务器端函数必须实现自己的类,该类继承signalr的hub类)

比如,我新建了一个文件夹叫Hubs,用于存放与signalr操作相关的文件。在hubs文件夹中新建了一个MessageHub.cs类,该类继承Hub类

[csharp] view plaincopy

  1. public class MessageHub: Hub
  2. {
  3. public void NoticeUser()
  4. {
  5. Clients.User(UserId).newLog();
  6. }
  7. }

完成后,浏览器端一旦连接上MessageHub后,就可以调用服务器端的NoticeUser函数。

3.添加Startup.cs

在项目中新建类文件,命名为:Startup.cs,内容为:

[csharp] view plaincopy

  1. <span style="font-size:12px;">using Microsoft.AspNet.SignalR;
  2. using Microsoft.Owin;
  3. using Owin;
  4. [assembly: OwinStartup(typeof(Sample.Startup))]
  5. namespace Sample
  6. {
  7. public class Startup
  8. {
  9. public void Configuration(IAppBuilder app)
  10. {
  11. //使用自己的idprovider,文章后面有介绍,如果不需要可以删除这两行
  12. var idProvider = new CustomUserIdProvider();
  13. GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => idProvider);
  14. // Any connection or hub wire up and configuration should go here
  15. app.MapSignalR();
  16. }
  17. }
  18. }</span>

浏览器端:

3.添加script引用,添加必要的script代码:

[javascript] view plaincopy

  1. <span style="font-size:12px;">$(function () {
  2. //创建与服务器的连接,指定连接到MessageHub这个hub类(注意MessageHub的m小写)
  3. var chat = $.connection.messageHub;
  4. //定义浏览器端函数,该函数可通过服务器端的hub类中调用
  5. chat.client.newLog = function () {
  6. //some code by yourself
  7. }
  8. //启动signalr的与服务器的连接
  9. $.connection.hub.start();
  10. })</span>

其中newlog是我自己定义的函数,你可以根据自己的需要定义多个别的函数。

4.如何指定自己的connectionId(往往使用自己系统中原有的成员关系),实现发送给指定用户消息

SignalR的微软官网中介绍了大部分的功能,你可以直接参考:

http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-getting-started-with-signalr-20-and-mvc-5

但是这些介绍中只介绍了如何广播,并没有详细介绍怎么给指定的某个用户发送消息

比如在笔者所参与的项目中,系统原本有一套成员关系表,每个登陆到web项目中的用户,都有自己的用户名,id和密码等信息。

默认情况下,当某个客户端通过SignalR连接到服务器时,SignalR帮我们动态的制定了一个ConnectionId,你可以通过这个ConnectionId去给指定的某个用户发消息。但是这样的效果往往不是我们想要的。我们希望使用系统原有的成员Id作为这个ConnectionId。

比如系统中的用户A,希望发送一则消息给用户B,那么在使用SignalR的:Clients.User(userId).send(message);

但是这里的userId希望使用系统自己的用户成员关系

因此可以自定义IUserIdProvider类,比如我的系统中:

[csharp] view plaincopy

  1. public class CustomUserIdProvider : IUserIdProvider
  2. {
  3. public string GetUserId(IRequest request)
  4. {
  5. var userId = WebSecurity.CurrentUserId;
  6. return userId.ToString();
  7. }
  8. }

5.直接从服务器端调用某用户前端函数

正如上面所讲的那样,普通的通讯模式为:

1)客户端A在页面中触发某一事件(比如点击某个button)

2)在button.click的事件处理函数中调用了SignalR的某一函数,比如上面讲到的noticeUser函数

3)该noticeUser函数为服务器端方法,所以客户A的前端会通过SignalR调用服务器端的noticeUser方法

4)服务器会根据客户端A调用newlog时传递的若干参数(其中通常包括一个id号,即客户端A想要发送消息给哪个用户,比如客户端B。当然,如果你可以在服务器中通过其他业务查询的到,也可不必传递这个id参数),通过SignalR调用指定Id号的客户端的某个函数,比如上面提到的newlog方法

有时候,由于系统的业务需求,可能需要直接在服务器端调用noticeUser函数,或者直接调用客户端B的newlog函数。比如客户端A提交某个form表单后,服务器端处理完成form表单的数据,存入数据库,然后想通知客户端B,有新消息。此时,不希望直接在客户端A的前段调用noticeUser,然后在经过服务器调用newlog。而希望直接在服务器调用newlog。

其实很简单,你只需要在你需要调用的地方添加如下代码即可:

[csharp] view plaincopy

  1. //call client method on server but not in hub class
  2. IHubContext _hubContext = GlobalHost.ConnectionManager.GetHubContext<MessageHub>();
  3. _hubContext.Clients.User(docUserId.ToString()).newLog();

注:

笔者也是由于项目需要,刚接触SignalR不久,对内部机理并不是很熟悉。在使用的过程中遇到了不少麻烦,因此写出这篇文章希望对初用者有帮助。如有问题请留言交流。
本文为原创,如需转载请注明。谢谢!

时间: 2024-10-29 08:49:40

ASP.NET MVC4使用SignalR实现实时通讯的相关文章

C# ASP.NET MVC 之 SignalR 学习 实时数据推送显示 配合 Echarts 推送实时图表

本文主要是我在刚开始学习 SignalR 的技术总结,网上找的学习方法和例子大多只是翻译了官方给的一个例子,并没有给出其他一些经典情况的示例,所以才有了本文总结,我在实现推送简单的数据后,就想到了如何去推送复杂的数据,以及推送一个实时的图表数据,文本为我原创,转载请注明出处:Richard.Hu,先上一堆乱七八糟的说明先: SignalR的官方地址是: https://www.asp.net/signalr 网上给出例子是一个聊天的例子,官网地址是:https://docs.microsoft.

第五章SignalR的实时高频通讯

第五章SignalR的实时高频通讯 概述:本例子演示了如果创建一个对象与其他浏览器共享实时状态的应用程序.我们要创建的应用程序为"MoveShape",该MoveShape页面会显示一个Html Div元素,用户可以拖动,并且在用户拖动时,该元素的新位置将被发送到服务器,这样,其他所有已连接的客户端都会同步更新该元素的位置. 在这个例子中使用的应用程序是基于迪米安·爱德华兹的Demo制作的,你可以在这里看到该视频. 本例子将演示从形状的拖动事件引发时,如何发送SignalR消息开始,至

实时通讯

过完2018年最后一个长假,看了年初给自己的flag,默默的发现距离感还是很强的.... 先说正题,最近在项目中碰到了实时通讯的需求,翻看了很多资料,最终选取signalr. 附上链接https://www.asp.net/signalr 项目是基于Angular4的,后端采用的Abp框架,自带通知架构.(https://aspnetboilerplate.com/Pages/Documents/Notification-System) 先说怎么将signalr引入项目中. 1.npm i si

Asp.NET MVC3 使用 SignalR 实现推送

一,简介 Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架.它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请求或使用轮询技术来获取消息. 二,实现机制 SignalR 的实现机制与 .NET WCF 或 Remoting 是相似的,都是使用远程代理来实现.在具体使用上,有两种不同目的的接口:PersistentConnection 和 Hubs,其中 PersistentConnection 是实现了长

Node.js 切近实战(十一) 之实时通讯

曾经在幽幽暗暗反反复复中追问,才知道平平淡淡从从容容才是真,听着歌曲,写博客,感觉就来了. 今天我们主要看一下Socket.IO实时通讯,先看一下界面. .row  .col-md-9   .panel.panel-primary    .panel-heading     h3.panel-title(style='font-size:13px;') Chat Message    .panel-body#div_msgbody(style='min-height:590px;max-heig

SignalR实现实时日志监控

.net SignalR实现实时日志监控 摘要 昨天吃饭的时候,突然想起来一个好玩的事,如果能有个页面可以实时的监控网站或者其他类型的程序的日志,其实也不错.当然,网上也有很多成熟的类似的监控系统.就想着如果通过.net该如何实现?所以就在想,通过系统内部将消息推送到前端,.net中可以通过pull或者push的方式,pull通常的做法就是ajax方式不停的请求一个接口,这种方式,不太理想.然后就在想如何通过服务端想客户端推送消息.之前看到过SignalR方面的文章可以实现push的功能,sig

Asp.Net MVC4.0 官方教程 入门指南之四--添加一个模型

Asp.Net MVC4.0 官方教程 入门指南之四--添加一个模型 在这一节中,你将添加用于管理数据库中电影的类.这些类是ASP.NET MVC应用程序的模型部分. 你将使用.NET Framework框架下的实体框架(Entity Framework)数据访问技术,与模型类协同工作.实体框架(常简称为EF)支持一种称之为编码先行(Code First)的开发模式.编码先行使你通过编写简单的类(简称为POCO类,全称为"plain-old CLR objects."),来创建模型对象

构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(30)-本地化(多语言)

原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(30)-本地化(多语言) 我们的系统有时要扩展到其他国家,或者地区,需要更多的语言环境,微软提供了一些解决方案,原始我们是用js来控制的,现在不需要了. 我们只要创建简单的资源文件,通过MVC的路由设置就可以轻松的进行语言中的切换. 本节受益于:Asp.net MVC3 高级编程第121页.大家可以自行百度这本书,这应该是国内第一本中文版的MVC3.0教程 现在从项目入手吧(本节也适合其他MVC程序),

ASP.NET MVC4+BootStrap 实战(二)

上一篇文章我们讲述了页面初始加载数据的一些东西,本篇我们来讲一下查询按钮和分页按钮.在很久以前我写过一篇ASP.NET MVC4切近实战的文章,有关于分页的代码,本篇我们不采用微软的AJAX框架. 先看一下查询效果,在点击Get按钮之后,会进行AJAX请求. js代码如下 jQuery(document).ready(function () {     setRowBackColor();     $("#btnsearch").click(function () {