SignalR 简介

作者 :Patrick Fletcher

警告

本文档不适用于最新版本的 SignalR。 查看 ASP.NET Core SignalR

本文介绍 SignalR 是什么,以及它旨在创建的一些解决方案。

问题和评论

请留下反馈,说明你如何喜欢本教程,以及我们可以在页面底部的评论中改进的内容。 如果你有与本教程不直接相关的问题,可以将其发布到 ASP.NET SignalR 论坛StackOverflow.com

什么是 SignalR?

ASP.NET SignalR 是一个面向 ASP.NET 开发人员的库,可简化向应用程序添加实时 Web 功能的过程。 实时 Web 功能是让服务器代码在可用时立即将内容推送到连接的客户端,而不是让服务器等待客户端请求新数据。

SignalR 可用于向 ASP.NET 应用程序添加任何类型的“实时”Web 功能。 虽然聊天通常用作示例,但你可以执行更多操作。 每当用户刷新网页以查看新数据,或页面实现 长时间轮询 以检索新数据时,它都是使用 SignalR 的候选项。 示例包括仪表板和监视应用程序、协作应用程序 (,例如同时编辑文档) 、作业进度更新和实时表单。

SignalR 还支持需要服务器进行高频率更新的全新 Web 应用程序类型,例如实时游戏。

SignalR 提供了一个简单的 API,用于创建服务器到客户端远程过程调用, (RPC) 调用客户端浏览器中的 JavaScript 函数, (和其他客户端平台从服务器端 .NET 代码) 。 SignalR 还包括用于连接管理的 API (例如,连接和断开连接事件) ,以及分组连接。

使用 SignalR 调用方法

SignalR 自动处理连接管理,让你可同时向所有连接的客户端广播消息,就像聊天室一样。 也可以向特定客户端发送消息。 客户端和服务器之间的连接是持久的,不同于传统的 HTTP 连接,后者针对每次通信重新建立。

SignalR 支持“服务器推送”功能,其中服务器代码可以使用远程过程调用 (RPC) 在浏览器中调用客户端代码,而不是目前 Web 上常见的请求-响应模型。

SignalR 应用程序可以使用内置和第三方横向扩展提供程序横向扩展到数千个客户端。

内置提供程序包括:

第三方提供程序包括:

SignalR 是开源的,可通过 GitHub 访问

SignalR 和 WebSocket

SignalR 在可用的情况下使用新的 WebSocket 传输,并在必要时回退到旧传输。 虽然当然可以直接使用 WebSocket 编写应用,但使用 SignalR 意味着需要实现的许多额外功能已经为你完成。 最重要的是,这意味着你可以编写应用代码以利用 WebSocket,而无需担心为旧客户端创建单独的代码路径。 SignalR 还可以避免担心 WebSocket 的更新,因为 SignalR 已更新以支持基础传输中的更改,从而为应用程序提供跨 WebSocket 版本的一致接口。

传输和回退

SignalR 是客户端和服务器之间执行实时工作所需的某些传输的抽象。 如果可能,SignalR 首先尝试建立 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 请求,服务器可以使用该请求将数据推送到客户端,而无需客户端专门请求它。

  • Internet Explorer 的永久帧 (仅) 。 Forever Frame 创建一个隐藏的 IFrame,该 IFrame 向服务器上未完成的终结点发出请求。 然后,服务器会不断向立即执行的客户端发送脚本,从而提供从服务器到客户端的单向实时连接。 从客户端到服务器的连接使用从服务器到客户端连接的单独连接,并且与标准 HTTP 请求一样,会为需要发送的每个数据段创建一个新连接。
  • Ajax 长轮询。 长轮询不会创建持久连接,而是使用一个请求轮询服务器,该请求一直保持打开状态,直到服务器响应,此时连接将关闭,并立即请求新连接。 这可能会在连接重置时引入一些延迟。

有关哪些配置支持哪些传输的详细信息,请参阅 支持的平台

传输选择过程

以下列表显示了 SignalR 用于确定要使用的传输的步骤。

  1. 如果浏览器是 Internet Explorer 8 或更早版本,则使用长轮询。

  2. 如果 (配置 JSONP, jsonp 则当) 启动连接时,参数设置为 true ,则使用长轮询。

  3. 如果正在 (建立跨域连接,也就是说,如果 SignalR 终结点与托管页) 不在同一域中,则如果满足以下条件,则将使用 WebSocket:

    • 客户端支持 CORS (跨域资源共享) 。 有关哪些客户端支持 CORS 的详细信息,请参阅 caniuse.com 中的 CORS

    • 客户端支持 WebSocket

    • 服务器支持 WebSocket

      如果未满足上述任何条件,则将使用长轮询。 有关跨域连接的详细信息,请参阅 如何建立跨域连接

  4. 如果未配置 JSONP 并且连接不是跨域连接,则客户端和服务器都支持时,将使用 WebSocket。

  5. 如果客户端或服务器不支持 WebSocket,则使用服务器发送事件(如果可用)。

  6. 如果服务器发送的事件不可用,则尝试永远帧。

  7. 如果 Forever Frame 失败,则使用长轮询。

监视传输

可以通过在中心上启用日志记录并在浏览器中打开控制台窗口来确定应用程序正在使用的传输。

若要在浏览器中为中心的事件启用日志记录,请将以下命令添加到客户端应用程序:

$.connection.hub.logging = true;

  • 在 Internet Explorer 中,按 F12 打开开发人员工具,然后单击“控制台”选项卡。

    Microsoft Internet Explorer 中的控制台

  • 在 Chrome 中,按 Ctrl+Shift+J 打开控制台。

    Google Chrome 中的控制台

打开控制台并启用日志记录后,你将能够看到 SignalR 正在使用哪种传输。

显示 WebSocket 传输的 Internet Explorer 中的控制台

指定传输

协商传输需要一定的时间和客户端/服务器资源。 如果客户端功能已知,则可以在客户端连接启动时指定传输。 以下代码片段演示如何使用 Ajax Long Polling 传输启动连接,如果已知客户端不支持任何其他协议,将使用该传输:

connection.start({ transport: 'longPolling' });

如果希望客户端按顺序尝试特定传输,可以指定回退顺序。 以下代码片段演示了如何尝试 WebSocket 并失败,直接转到长轮询。

connection.start({ transport: ['webSockets','longPolling'] });

用于指定传输的字符串常量定义如下:

  • webSockets
  • foreverFrame
  • serverSentEvents
  • longPolling

连接和中心

SignalR API 包含用于在客户端和服务器之间进行通信的两个模型:持久连接和中心。

连接表示用于发送单一收件人、分组或广播消息的简单终结点。 持久连接 API (由 PersistentConnection 类) 在 .NET 代码中表示,使开发人员能够直接访问 SignalR 公开的低级别通信协议。 使用基于连接的 API(如 Windows Communication Foundation)的开发人员会熟悉使用连接通信模型。

中心是基于连接 API 构建的更高级别管道,它允许客户端和服务器直接相互调用方法。 SignalR 像使用 magic 一样处理跨计算机边界的调度,使客户端能够像本地方法一样轻松地在服务器上调用方法,反之亦然。 使用 .NET 远程处理等远程调用 API 的开发人员会熟悉使用中心通信模型。 使用中心还可以将强类型参数传递给方法,从而启用模型绑定。

体系结构关系图

下图显示了中心、持久连接和用于传输的基础技术之间的关系。

显示 API、传输和客户端的 SignalR 体系结构图

中心的工作原理

当服务器端代码在客户端上调用方法时,会通过活动传输发送一个数据包,其中包含要调用的方法的名称和参数, (当对象作为方法参数发送时,将使用 JSON) 对其进行序列化。 然后,客户端将方法名称与客户端代码中定义的方法匹配。 如果存在匹配项,将使用反序列化的参数数据执行客户端方法。

可以使用 Fiddler 等工具来监视方法调用。下图显示了 Fiddler 的“日志”窗格中从 SignalR 服务器发送到 Web 浏览器客户端的方法调用。 方法调用是从名为 的中心 MoveShapeHub发送的,所调用的方法称为 updateShape

显示 SignalR 流量的 Fiddler 日志视图

在此示例中,中心名称使用 H 参数标识;方法名称由 M 参数标识,发送到方法的数据使用 A 参数标识。 生成此消息的应用程序是在 高频实时 教程中创建的。

选择通信模型

大多数应用程序都应使用中心 API。 连接 API 可在以下情况下使用:

  • 需要指定发送的实际消息的格式。
  • 开发人员更喜欢使用消息传递和调度模型,而不是远程调用模型。
  • 正在移植使用消息传递模型的现有应用程序以使用 SignalR。