实时Web应用程序能够实时地将服务器端内容推送到连接的客户端。对于ASP.NET开发人员,ASP.NET SignalR是一个向其应用程序添加实时Web功能的库。它利用了多种传输方式,根据客户端和服务器的最佳可用传输自动选择最佳可用传输。它利用了WebSocket,这是一种支持浏览器和服务器之间双向通信的HTML5 API。

SignalR还提供了一个简单的高级API,用于在ASP.NET应用程序中执行服务器到客户端RPC(在客户端的浏览器中从服务器端.NET代码调用JavaScript函数),以及为连接管理添加有用的钩子,例如连接/断开事件,分组连接和授权。

SignalR是对客户端和服务器之间进行实时工作所需的一些传输的抽象。一个SignalR连接开始为HTTP,然后提升到一个网页套接字(如果可用)连接。WebSocket是SignalR的理想传输,因为它可以最有效地使用服务器内存,具有最低的延迟,并具有最基本的功能(例如客户端和服务器之间的全双工通信),但它也有最严格的要求:WebSocket要求服务器使用Windows Server 2012或Windows 8以及.NET Framework 4.5。如果不满足这些要求,SignalR将尝试使用其他传输来建立连接(如Ajax长轮询)。

该SignalR API包含了客户端和服务器之间的通信两种型号:永久连接和枢纽。阿连接代表用于发送单收件人,分组,或广播消息的简单端点。一个中心是于连接API,可让您的客户端和服务器直接调用对方的方法建立了一个更高层的管道。

概观

目标

  • 使用SignalR从服务器向客户端发送通知。
  • 使用SQL Server扩展SignalR应用程序。

练习1:使用SignalR处理实时数据
虽然聊天通常用作示例,但您可以使用实时Web功能完成更多工作。每当用户刷新网页以查看新数据或页面实现Ajax长轮询以检索新数据时,您都可以使用SignalR。

SignalR支持服务器推送或广播功能; 它自动处理连接管理。在用于客户端 - 服务器通信的经典HTTP连接中,为每个请求重新建立连接,但SignalR提供客户端和服务器之间的持久连接。在SignalR中,服务器代码使用远程过程调用(RPC)调用浏览器中的客户端代码,而不是我们今天所知的请求 - 响应模型。

在本练习中,您将配置Geek Quiz应用程序以使用SignalR显示带有更新指标的Statistics仪表板,而无需刷新整个页面。

任务1 - 探索极客测验统计页面
在此任务中,您将浏览应用程序并验证统计信息页面的显示方式以及如何改进信息的更新方式。

打开Visual Studio Express 2013 for Web并打开位于Source \ Ex1-WorkingWithRealTimeData \ Begin文件夹中的GeekQuiz.sln解决方案。

按F5运行解决方案。将在登录页面应该出现在浏览器中。
运行解决方案

单击页面右上角的“ 注册”以在应用程序中创建新用户。
注册链接

在“ 注册”页面中,输入“ 用户名”和“ 密码”,然后单击“ 注册”。
注册用户

应用程序注册新帐户,用户通过身份验证并重定向回显示第一个测验问题的主页。

在新窗口中打开Statistics页面,并将Home页面和Statistics页面并排放置。
并排的窗户

在主页中,单击其中一个选项来回答问题。
回答问题

单击其中一个按钮后,应显示答案。
问题回答正确

请注意,“统计信息”页面中提供的信息已过时。刷新页面以查看更新的结果。

统计页面

返回Visual Studio并停止调试。

任务2 - 将SignalR添加到Geek测验以显示在线图表
在此任务中,您将向解决方案添加SignalR,并在向服务器发送新答案时自动向客户端发送更新。

从Visual Studio 的“ 工具”菜单中,选择“ NuGet包管理器”,然后单击“ 包管理器控制台”。

在“ 程序包管理器控制台”窗口中,执行以下命令:

Install-Package Microsoft.AspNet.SignalR

在Solution Explorer中,右键单击GeekQuiz项目,选择Add | 新建文件夹,并将其命名为Hubs。

右键单击Hubs文件夹,然后选择Add | 新文件夹。
添加新项目

在“ 添加新项”对话框中,选择“ Visual C#” 网络| 在左窗格中的SignalR节点,从中心窗格中选择SignalR Hub Class(v2),将文件命名为StatisticsHub.cs,然后单击Add。
添加新项目对话框

使用以下代码替换StatisticsHub类中的代码。

(代码片段 - RealTimeSignalR - Ex1 - StatisticsHubClass)

namespace GeekQuiz.Hubs
{
using Microsoft.AspNet.SignalR;
public class StatisticsHub : Hub
{
}
}

打开Startup.cs并在Configuration方法的末尾添加以下行。

(代码片段 - RealTimeSignalR - Ex1 - MapSignalR)

public void Configuration(IAppBuilder app)
{
this.ConfigureAuth(app);
app.MapSignalR();
}

打开Services文件夹中的StatisticsService.cs页面,并添加以下using指令。

(代码片段 - RealTimeSignalR - Ex1 - UsingDirectives)

using Microsoft.AspNet.SignalR;
using GeekQuiz.Hubs;

要通知连接的客户端更新,首先要检索当前连接的Context对象。该中心对象包含的方法将消息发送到一个单一的客户端或广播到所有连接的客户端。将以下方法添加到StatisticsService类以广播统计数据。

(代码片段 - RealTimeSignalR - Ex1 - NotifyUpdatesMethod)

public async Task NotifyUpdates()
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<StatisticsHub>();
if (hubContext != null)
{
var stats = await this.GenerateStatistics();
hubContext.Clients.All.updateStatistics(stats);
}
}

打开Controllers文件夹中的TriviaController.cs页面,并添加以下using指令。
using GeekQuiz.Services;
将以下突出显示的代码添加到Post操作方法。

(代码片段 - RealTimeSignalR - Ex1 - NotifyUpdatesCall)

public async Task<IHttpActionResult> Post(TriviaAnswer answer)
{
if (!ModelState.IsValid)
{
return this.BadRequest(this.ModelState);
}
answer.UserId = User.Identity.Name;
var isCorrect = await this.StoreAsync(answer);
var statisticsService = new StatisticsService(this.db);
await statisticsService.NotifyUpdates();
return this.Ok<bool>(isCorrect);
}

打开Views |中的Statistics.cshtml页面 家庭文件夹。找到“ 脚本”部分,并在该部分的开头添加以下脚本引用。

(代码片段 - RealTimeSignalR - Ex1 - SignalRScriptReferences)

@section Scripts {
@Scripts.Render("~/Scripts/jquery.signalR-2.0.2.min.js");
@Scripts.Render("~/signalr/hubs");
...
}

注意

将SignalR和其他脚本库添加到Visual Studio项目时,程序包管理器可能会安装一个版本比本主题中显示的版本更新的SignalR脚本文件。确保代码中的脚本引用与项目中安装的脚本库的版本相匹配。

添加以下突出显示的代码以将客户端连接到SignalR集线器,并在从集线器收到新消息时更新统计数据。

(代码片段 - RealTimeSignalR - Ex1 - SignalRClientCode)

@section Scripts {
...
<script>
...
var connection = $.hubConnection();
var hub = connection.createHubProxy("StatisticsHub");
hub.on("updateStatistics", function (statistics) {
statisticsData = statistics;
$("#correctAnswersCounter").text(statistics.CorrectAnswers);
$("#incorrectAnswersCounter").text(statistics.IncorrectAnswers);
showCharts(statisticsData);
});
connection.start();
</script>
}

在此代码中,您将创建一个Hub Proxy并注册一个事件处理程序来侦听服务器发送的消息。在这种情况下,您将侦听通过updateStatistics方法发送的消息。

任务3 - 运行解决方案
在此任务中,您将运行解决方案以验证在回答新问题后使用SignalR自动更新统计信息视图。

按F5运行解决方案。

在新窗口中打开Statistics页面,并像在任务1中一样并排放置Home页面和Statistics页面。

练习2:使用SQL Server进行扩展
扩展Web应用程序时,通常可以选择扩展和扩展选项。向上扩展意味着使用更大的服务器,具有更多资源(CPU,RAM等),而向外扩展意味着添加更多服务器来处理负载。后者的问题是客户端可以路由到不同的服务器。连接到一台服务器的客户端将不会接收从另一台服务器发送的消息。

您可以使用名为backplane的组件在服务器之间转发消息来解决这些问题。启用背板后,每个应用程序实例都会向背板发送消息,背板会将消息转发给其他应用程序实例。

SignalR目前有三种方式:

Windows Azure Service Bus。Service Bus是一种消息传递基础结构,允许组件发送松散耦合的消息。
SQL Server。SQL Server底板将消息写入SQL表。背板使用Service Broker进行有效的消息传递。但是,如果未启用Service Broker,它也可以使用。
Redis。Redis是一个内存中的键值存储。Redis支持发送/订阅(“pub / sub”)模式以发送消息。
每条消息都通过消息总线发送。消息总线实现IMessageBus接口,该接口提供发布/订阅抽象。背板通过使用为该背板设计的总线替换默认IMessageBus来工作。

每个服务器实例通过总线连接到背板。发送消息时,它会进入背板,背板会将其发送到每个服务器。当服务器从背板接收消息时,它会将消息存储在其本地缓存中。然后,服务器从其本地缓存向客户端传递消息。

有关SignalR背板如何工作的更多信息,请阅读本文。

注意:在某些情况下,背板可能成为瓶颈。以下是一些典型的SignalR场景:

服务器广播(例如,股票代码):背板适用于此场景,因为服务器控制消息的发送速率。
客户端到客户端(例如,聊天):在这种情况下,如果消息数量与客户端数量成比例,则背板可能是瓶颈; 也就是说,如果消息的速率随着更多客户端的加入而成比例增长。
高频实时(例如,实时游戏):不建议在这种情况下使用背板。
在本练习中,您将使用SQL Server在Geek Quiz应用程序中分发消息。您将在单个测试计算机上运行这些任务以了解如何设置配置,但为了获得完整的效果,您需要将SignalR应用程序部署到两个或更多服务器。您还必须在其中一台服务器上或单独的专用服务器上安装SQL Server。

任务1 - 了解场景
在此任务中,您将运行2个Geek Quiz实例,模拟本地计算机上的多个IIS实例。在这种情况下,当在一个应用程序上回答琐事问题时,将不会在第二个实例的统计页面上通知更新。此模拟类似于将应用程序部署在多个实例上并使用负载平衡器与它们进行通信的环境。

打开位于Source / Ex2-ScalingOutWithSQLServer / Begin文件夹中的Begin.sln解决方案。加载后,您会在Server Explorer上注意到该解决方案有两个结构相同但名称不同的项目。这将模拟在本地计算机上运行同一应用程序的两个实例。
开始解决方案模拟Geek测验的2个实例

右键单击解决方案节点并选择“ 属性”,打开解决方案的属性页面。在“ 启动项目”下,选择“ 多个启动项目”并将两个项目的“操作”值更改为“ 启动”。
启动多个项目

按F5运行解决方案。该应用程序将在不同的端口启动两个Geek Quiz实例,模拟同一应用程序的多个实例。将其中一个浏览器固定在屏幕右侧,另一个固定在屏幕右侧。使用您的凭据登录或注册新用户。登录后,将Trivia页面保留在左侧,然后转到右侧浏览器中的Statistics页面。

在左侧浏览器中开始回答问题,您会注意到右侧浏览器中的“ 统计”页面未更新。这是因为SignalR使用本地缓存在其客户端上分发消息,并且此方案模拟多个实例,因此不在它们之间共享缓存。您可以通过测试相同的步骤但使用单个应用来验证SignalR是否正常工作。在以下任务中,您将配置以跨实例复制消息。

返回Visual Studio并停止调试。

任务2 - 创建SQL Server数据库
在此任务中,您将创建一个数据库,作为Geek Quiz应用程序的数据源。您将使用SQL Server对象资源管理器浏览您的服务器并初始化数据库。此外,您将启用Service Broker。

在Visual Studio中,打开菜单查看并选择SQL Server对象资源管理器。

通过右键单击“ SQL Server”节点并选择“ 添加SQL Server …”选项,连接到LocalDB实例。
将SQL Server实例添加到SQL Server对象资源管理器

将服务器名称设置为(localdb)\ v11.0,并将Windows身份验证保留为身份验证模式。单击“ 连接”继续。
连接到LocalDB

现在您已连接到LocalDB实例,您将需要创建一个名为SignalR的SQL Server数据库。为此,请右键单击“ 数据库”节点,然后选择“ 添加新数据库”。
添加新数据库

将数据库名称设置为SignalR,然后单击“ 确定”以创建它。
创建SignalR数据库

注意:您可以为数据库选择任何名称。

要从背板更有效地接收更新,建议为数据库启用Service Broker。Service Broker为SQL Server中的消息传递和排队提供本机支持。背板也可以在没有Service Broker的情况下工作。通过右键单击数据库并选择“ 新建查询”来打开新查询。
打开新查询

要检查Service Broker是否已启用,请查询sys.databases目录视图中的is_broker_enabled列。在最近打开的查询窗口中执行以下脚本。

SELECT [name], [service_broker_guid], [is_broker_enabled] FROM [master].[sys].[databases]

查询Service Broker状态
如果数据库中is_broker_enabled列的值为“0”,请使用以下命令启用它。将替换为您在创建数据库时设置的名称(例如:SignalR)。

ALTER DATABASE <YOUR-DATABASE> SET ENABLE_BROKER

启用Service Broker
注意:如果此查询似乎死锁,请确保没有应用程序连接到数据库。

任务3 - 配置SignalR应用程序
在此任务中,您将配置Geek Quiz以连接到SQL Server后台。您将首先添加SignalR.SqlServer NuGet包并将连接字符串设置为您的组件数据库。

从Tools > NuGet Package Manager打开Package Manager控制台。确保在“ 默认项目”下拉列表中选择了GeekQuiz项目。键入以下命令以安装Microsoft.AspNet.SignalR.SqlServer NuGet包。

Install-Package Microsoft.AspNet.SignalR.SqlServer
重复上一步,但这次是项目GeekQuiz2。

要配置SQL Server组件,请打开GeekQuiz项目的Startup.cs文件,并将以下代码添加到Configure方法中。将替换为您在创建SQL Server后台时使用的数据库名称。对GeekQuiz2项目重复此步骤。

(代码片段 - RealTimeSignalR - Ex2 - StartupConfiguration)

public class Startup
{
public void Configuration(IAppBuilder app)
{
var sqlConnectionString = @"Server=(localdb)\v11.0;Database=<YOUR-DATABASE>;Integrated Security=True;";
GlobalHost.DependencyResolver.UseSqlServer(sqlConnectionString);
this.ConfigureAuth(app);
app.MapSignalR();
}
}

既然两个项目都配置为使用SQL Server组件,请按F5同时运行它们。

同样,Visual Studio将在不同的端口启动两个Geek Quiz实例。将其中一个浏览器固定在屏幕右侧,另一个固定在屏幕右侧,然后使用您的凭据登录。将Trivia页面保留在左侧,然后转到右侧浏览器的Statistics页面。

开始在左侧浏览器中回答问题。这次,由于背板,统计页面会更新。在应用程序之间切换(统计信息现在位于左侧,Trivia位于右侧)并重复测试以验证它是否适用于两个实例。后台用作每个连接的服务器的消息的共享缓存,并且每个服务器将消息存储在它们自己的本地缓存中以分发给连接的客户端。

返回Visual Studio并停止调试。

SQL Server后台自动在指定的数据库上生成必要的表。在SQL Server对象资源管理器面板中,打开为背板创建的数据库(例如:SignalR)并展开其表。您应该看到以下表格:

背板生成表

右键单击SignalR.Messages_0表,然后选择“ 查看数据”。
查看SignalR背板消息表

在回答问题时,您可以看到发送到Hub的不同消息。后台将这些消息分发给任何连接的实例。

http://net-yuan.com

使用SignalR实时Web应用程序的更多相关文章

  1. Node.js高级编程读书笔记 - 4 构建Web应用程序

    Outline 5 构建Web应用程序 5.1 构建和使用HTTP中间件 5.2 用Express.js创建Web应用程序 5.3 使用Socket.IO创建通用的实时Web应用程序 5 构建Web应 ...

  2. [ASP.NET] 使用 ASP.NET SignalR 添加实时 Web

    ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务 ...

  3. 使用SignalR+Asp.net创建实时聊天应用程序

    一.概述: 使用 ASP.NET 那么 SignalR 2 创建一个实时聊天应用程序.将 SignalR 添加 MVC 5 应用程序中,并创建聊天视图发送并显示消息. 在Demo中,将学习Signal ...

  4. SignalR来做实时Web聊天

    本章和大家分享的内容是使用Signal R框架创建个简易的群聊功能,主要讲解如何在.Net的MVC中使用这个框架,由于这个项目有官方文档(当然全英文),后面也不打算写分享篇了,主要目的是让朋友们在需要 ...

  5. 【转】SignalR来做实时Web聊天

    本章和大家分享的内容是使用Signal R框架创建个简易的群聊功能,主要讲解如何在.Net的MVC中使用这个框架,由于这个项目有官方文档(当然全英文),后面也不打算写分享篇了,主要目的是让朋友们在需要 ...

  6. 使用Node.js的socket.io模块开发实时web程序

    首发:个人博客,更新&纠错&回复 今天的思维漫游如下:从.net的windows程序开发,摸到nodejs的桌面程序开发,又熟悉了一下nodejs,对“异步”的理解有了上上周对操作系统 ...

  7. 一步一步学习SignalR进行实时通信_9_托管在非Web应用程序

    原文:一步一步学习SignalR进行实时通信_9_托管在非Web应用程序 一步一步学习SignalR进行实时通信\_9_托管在非Web应用程序 一步一步学习SignalR进行实时通信_9_托管在非We ...

  8. SignalR + Mvc 4 web 应用程序

    在上节中,我们已经初步对 SignalR 进行了了解,这一节我们将做一个SignalR Demon,具体的步骤如下: 1. 创建一个 mvc 4 web 应用程序,并选择 Basic 2. 创建一个 ...

  9. 实时web应用方案——SignalR(.net core)

    何为实时 先从理论上解释一下两者的区别. 大多数传统的web应用是这样的:客户端发起http请求到服务端,服务端返回对应的结果.像这样: 也就是说,传统的web应用都是客户端主动发起请求到服务端. 那 ...

随机推荐

  1. 一个U盘黑掉你:TEENSY实战(test)

    挖掘过程一: 自从上一次投稿,已经好久好久没写文章了.今天就着吃饭的时间,写篇文章,记录下自己学习xss这么久的心得.在我看来.Xss就是javascript注入,你可以在js语法规定的范畴内做任何事 ...

  2. [python] 列表解析式的高效与简洁

    方法一(列表解析式): list1 = ["abc","efg","hij"] list2 = [i[0] for i in list1] ...

  3. [Python] 启动 uiautomatorviewer2之后,连接成功后重新 reload画面时提示 ('Connection aborted.', error(10054, ''))

    [问题] 出现该问题不管是重启手机还是启动手机里面 uiautomator的服务,都无济于事,只有通过下面方法进行重新初使化方能解决问题 [解决方法] 在命令窗口执行如下命令 python -m ui ...

  4. linux结束程序内存不会马上释放的解决方法

      Linux下频繁读写文件时,内存资源被耗尽,当程序结束后,内存不会释放需要清除缓存.Linux缓存有dentry,buffer cache,page cache. 注:Dentry用来加速文件路径 ...

  5. C内存开辟与平移

  6. python第四十三课——封装性

    1.面向对象的三大特性:封装性.继承性.多态性 封装: 封装使用的领悟: 1).生活层面:食品.快递.计算机.明星... 2).计算机层面: ①.模块.类.函数... ②.属性数据的封装与隐藏 权限修 ...

  7. runloop是iOS系统上的actor模式

    runloop是iOS系统上的actor模式(单线程派发的)

  8. BZOJ3173:[TJOI2013]最长上升子序列(Splay)

    Description 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? Input 第一行一 ...

  9. 【转】Android Service创建USB HOST通信

    之前做了一个关于Android USB通信的Case,通过Android的USB总线给Zigbee供电,和板载的Zigbee(基于Zigbee的自组网)进行通信.要使用Android的USB Host ...

  10. 写出js内存泄漏的问题?

    回答一: (1)IE7/8 DOM对象或者Active对象循环引用导致内存泄漏 a.多个对象循环引用 b.循环的DOM泄漏 (2)基础的DOM泄漏 当原有的DOM被移除时,子节点引用没有被移除则无法回 ...