SignalR简介
什么是SignalR?
ASP.NET SignalR是ASP.NET开发人员的库,它简化了向应用程序添加实时Web功能的过程。实时网络功能可以让服务器代码在连接的客户端可用时立即将内容推送到连接的客户端,而不是让服务器等待客户端请求新数据。
SignalR可以用于向ASP.NET应用程序添加任何类型的“实时”Web功能。虽然聊天通常被用作一个例子,你可以做更多。每当用户刷新网页以查看新数据,或者页面实现长轮询以检索新数据时,它是使用SignalR的候选。示例包括仪表板和监视应用程序,协作应用程序(如同时编辑文档),作业进度更新和实时表单。
SignalR还支持需要从服务器进行高频更新的全新类型的Web应用程序,例如实时游戏。有关这方面的一个很好的例子,请参阅ShootR游戏。
SignalR提供了一个用于创建从服务器端.NET代码调用客户端浏览器(和其他客户端平台)中的JavaScript函数的服务器到客户端远程过程调用(RPC)的简单API。SignalR还包括用于连接管理(例如,连接和断开事件)的API和分组连接。
SignalR自动处理连接管理,并允许您同时向所有连接的客户端广播消息,如聊天室。您还可以向特定客户端发送消息。客户端和服务器之间的连接是持久的,不像为每个通信重新建立的传统HTTP连接。
SignalR支持“服务器推送”功能,其中服务器代码可以使用远程过程调用(RPC)在浏览器中调用客户端代码,而不是当今Web上常见的请求 - 响应模型。
SignalR应用程序可以使用Service Bus,SQL Server或Redis扩展到数千个客户端。
SignalR是开源的,可通过GitHub访问。
SignalR和WebSocket
SignalR在可用时使用新的WebSocket传输,并在必要时回退到旧的传输。虽然你可以直接使用WebSocket编写你的应用程序,但使用SignalR意味着你需要实现的很多额外的功能已经为你完成了。最重要的是,这意味着您可以编写应用程序以利用WebSocket,而无需担心为较旧的客户端创建单独的代码路径。SignalR还屏蔽了您不必担心WebSocket的更新,因为SignalR将继续更新以支持底层传输中的更改,从而为您的应用程序提供跨WebSocket版本的一致性界面。
虽然你当然可以单独使用WebSocket创建一个解决方案,SignalR提供了你自己需要的所有功能,例如回退到其他传输和修改你的应用程序更新WebSocket实现。
运输和回退
SignalR是对客户端和服务器之间进行实时工作所需的一些传输的抽象。SignalR连接以HTTP开头,然后升级到WebSocket连接(如果可用)。WebSocket是SignalR的理想传输,因为它可以最高效地使用服务器内存,具有最低的延迟,并且具有最底层的功能(如客户端和服务器之间的全双工通信),但它也具有最严格的要求:WebSocket要求服务器使用Windows Server 2012或Windows 8以及.NET Framework 4.5。如果不满足这些要求,SignalR将尝试使用其他传输进行连接。
HTML 5传输
这些传输依赖于对HTML 5的支持。如果客户端浏览器不支持HTML 5标准,将使用旧的传输。
- WebSocket(如果服务器和浏览器都指示他们可以支持Websocket)。WebSocket是唯一的在客户端和服务器之间建立真正的持久性,双向连接的传输。但是,WebSocket也有最严格的要求; 它仅在最新版本的Microsoft Internet Explorer,Google Chrome和Mozilla Firefox中完全受支持,并且仅在其他浏览器(如Opera和Safari)中部分实现。
- 服务器发送的事件,也称为EventSource(如果浏览器支持服务器发送事件,这基本上是除Internet Explorer之外的所有浏览器)。
彗星运输
以下传输基于Comet Web应用程序模型,其中浏览器或其他客户端维护长期保留的HTTP请求,服务器可以使用该请求将数据推送到客户端,而客户端没有明确请求它。
- Forever框架(仅限Internet Explorer)。Forever Frame创建一个隐藏的IFrame,它向服务器上的一个端点发出一个未完成的请求。服务器然后不断地向客户端发送脚本,该脚本被立即执行,提供从服务器到客户端的单向实时连接。从客户端到服务器的连接使用从服务器到客户端连接的单独连接,并且像标准HTML请求一样,为需要发送的每个数据段创建新连接。
- Ajax长轮询。长轮询不会创建持久连接,而是轮询服务器并保持打开的请求,直到服务器响应,此时连接关闭,并立即请求新连接。这可能会在连接重置时引入一些延迟。
有关哪些配置支持什么传输的详细信息,请参阅支持的平台。
运输选择过程
以下列表显示SignalR用于决定使用哪个传输的步骤。
- 如果浏览器是Internet Explorer 8或更早版本,则使用长轮询。
- 如果配置了JSONP(即,连接
jsonp
启动时将参数设置为true
),则使用长轮询。 -
如果正在进行跨域连接(即,如果SignalR端点与主机页不在同一个域中),则将在满足以下条件时使用WebSocket:
- 客户端支持CORS(跨源资源共享)。有关哪些客户端支持CORS的详细信息,请参阅caniuse.com上的CORS。
- 客户端支持WebSocket
-
服务器支持WebSocket
如果不满足任何这些标准,将使用长轮询。有关跨域连接的详细信息,请参阅如何建立跨域连接。
- 如果未配置JSONP并且连接不是跨域,则如果客户端和服务器都支持WebSocket,则将使用WebSocket。
- 如果客户端或服务器不支持WebSocket,则使用“服务器已发送事件”(如果可用)。
- 如果服务器发送的事件不可用,尝试永久帧。
- 如果Forever Frame失败,则使用长轮询。
监测运输
您可以通过在集线器上启用日志记录并在浏览器中打开控制台窗口来确定应用程序正在使用的传输方式。
要在浏览器中启用集线器事件的日志记录,请将以下命令添加到客户端应用程序:
$.connection.hub.logging = true;
-
在Internet Explorer中,按F12打开开发人员工具,然后单击控制台选项卡。
-
在Chrome中,按Ctrl + Shift + J打开控制台。
打开控制台并启用日志记录后,您将可以看到SignalR正在使用哪个传输。
指定传输
协商传输需要一定的时间和客户端/服务器资源。如果客户端能力已知,则可以在客户端连接启动时指定传输。以下代码片段演示了使用Ajax Long Polling传输启动连接,如果知道客户端不支持任何其他协议,则使用该代码:
connection.start({ transport: 'longPolling' });
如果您希望客户端按顺序尝试特定传输,则可以指定回退顺序。以下代码片段演示了尝试WebSocket,并且失败,直接转到长轮询。
connection.start({ transport: ['webSockets','longPolling'] });
用于指定传输的字符串常量定义如下:
webSockets
foreverFrame
serverSentEvents
longPolling
连接和集线器
SignalR API包含两个用于客户端和服务器之间通信的模型:持久连接和集线器。
连接表示用于发送单收件人,分组或广播邮件的简单端点。持久连接API(由PersistentConnection类在.NET代码中表示)使开发人员能够直接访问SignalR公开的低级通信协议。使用Connections通信模型对于使用基于连接的API(如Windows Communcation Foundation)的开发人员来说很熟悉。
Hub是一个构建在Connection API上的更高级别的管道,允许您的客户端和服务器直接相互调用方法。SignalR处理跨机器边界的调度,就像通过魔法,允许客户端像服务器本地方法一样轻松地调用方法,反之亦然。使用远程调用API(例如.NET Remoting)的开发人员将熟悉使用Hubs通信模型。使用Hub还允许您将强类型参数传递给方法,从而启用模型绑定。
建筑图
下图显示了集线器,持久连接和用于传输的基础技术之间的关系。
Hub如何工作
当服务器端代码在客户端上调用一个方法时,将通过活动传输发送一个包,其中包含要调用的方法的名称和参数(当对象作为方法参数发送时,将使用JSON序列化)。然后,客户端将方法名称与客户端代码中定义的方法进行匹配。如果存在匹配,则将使用反序列化的参数数据来执行客户端方法。
可以使用诸如Fiddler的工具来监视方法调用。下图显示了从Fiddler的Logs窗格中的SignalR服务器发送到Web浏览器客户端的方法调用。方法调用从MoveShapeHub
被调用的集线器发送,并且调用被调用的方法updateShape
。
在此示例中,集线器名称用H
参数标识; 方法名称用M
参数标识,并且发送到方法的数据用A
参数标识。生成此消息的应用程序在高频实时教程中创建。
选择通信模型
大多数应用程序应使用Hubs API。Connections API可用于以下情况:
- 必须指定发送的实际消息的格式。
- 开发人员更喜欢使用消息传递和调度模型,而不是远程调用模型。
- 使用消息传递模型的现有应用程序正在移植以使用SignalR。