ASP.NET SignalR是微软新开发的类库,为的是帮助ASP.NET开发人员很方便地开发实时网络功能。 SignalR允许服务器端和客户端之间进行双向通信。服务器端现在可以连接到客户端并且把内容瞬间推送出去,而不是一个客户端不断请求服务器端从而才能获取新数据(不是通过轮询去拉服务器端数据,而是服务器端主动推送数据到客户端)。SignalR支持Web Sockets套接字,并且当使用旧版浏览器的时候会自动使用相关兼容的技术。SignalR包括它的API接口,用于连接管理的解耦(例如,连接和断开连接的事件),群组连接接口和授权接口等。
SignalR可以为您的ASP.NET应用程序添加各种“实时”的Web功能。最常用的例子有聊天室,但当你使用SignalR后,我们可以比这做得更好更多。过去,用户需要通过不断刷新网页才能看到新的数据;或者在页面上通过实现长轮询来检索新数据(并显示),这些功能都会在在使用SignalR后变得更容易实现和使用。比如:仪表板及监视型应用程序、协作性应用程序(如多人同时对文档进行编辑)、作业进度更新及时呈现表单等。
SignalR也支持现在新类型的,需要从服务器上进行高频率的更新的Web应用程序,例如,实时游戏。对于这方面的一个很好的例子,请参见ShootR game.。
SignalR提供了一个简单的API,用于创建服务器到客户端的远程过程调用(RPC) ,从服务器端的.net代码调用客户端的浏览器(和其他客户端平台)的 JavaScript函数。SignalR还包括用于连接管理API (例如,连接和断开连接诶事件) ,群组连接和授权等。(简单来说,提供了服务器端API调用和客户端的JS事件)
SignalR可以自动对连接进行管理,并让您同时发送广播消息到所有连接的客户端,就像一个聊天室聊天一样。当然,您也可以选择向特定的用户(客户端)发送消息。客户端和服务器之间的连接是持久的,也就是通常我们所说的长连接,而不像一个典型的HTTP连接,每次通信都要重新建立连接。
SignalR支持“服务器推送”功能,即服务器代码可以通过使用远程过程调用(RPC)来调用浏览器中的客户端代码,而不是在Web网站上常见的【请求-响应模型】的形式去获取数据。
SignalR的应用通过使用服务总线(Service Bus)、SQL Server或Redis来扩展到数以万计的客户端上。
SignalR是开源的,通过GitHub.的访问来查看源码。
SignalR在支持HTML5的浏览器下,通常是使用WebSocket,来实现服务端跟客户端的通信。如果浏览器不支持WebSocket 那么他会自动切换支持该浏览器的其他的技术来实现(如Http长连接)。不管用哪种技术,最后都会实现同样的结果。当然,你也可以直接使用WebStocket来编写你的应用程序,但使用SignalR意味着你将有更多的额外功能而无需自己重新发明轮子(人家都写好接口了,拿来使用不是更好,何必自己重复建轮子)。最重要的是,你可以把时间和注意力放在业务实现上,而无需考虑为旧的客户端(IE9以下等)写兼容性代码。SignalR还能够使你不必担心WebStocket的更新,因为SignalR将会继续更新以及支持变化的底层传输方式,跨不同版本的WebStocket来为应用程序提供一个一致的访问接口。
当然,你可以创建只使用WebStocket传输的解决方案,SignalR提供了你可能需要自行编写代码的所有功能,比如回退到其他传输方式以及针对更新的WebStocket来实现修改您的应用程序。
2.1传输和协商转换(FallBacks):
SignalR是对客户端及服务器之间实时功能实现所需要的传输技术的抽象。SignalR首先使用HTTP的方式开始连接,并且检查WebSocket连接是否可用,如果可用,则会自动转为Webstocket连接。WebSocket是SignalR最理想的传输方式,因为它可以最有效地利用服务器内存,具有最低的延迟,并拥有最底层的功能(如客户端和服务器之间的全双工通信【双向通信】),但它也有最严格的要求:WebSocket的要求服务器必须使用Windows Server2012或Windows8,和NET框架4.5。如果不符合这些要求,SignalR将尝试使用其他传输方式进行连接。
2.1.1 HTML5的传输方式:(推荐使用谷歌浏览器作为主浏览器)
使用SignalR的任何传输方式都是取决于客户端浏览器是否支持HTML 5,如果客户端的浏览器不支持HTML5,将使用旧的传输方式。
1)WebSocket(如果服务器和浏览器都支持WebSocket的):WebSocket唯一一种在客户端和服务器端建立真实持久的双向连接的传输方式。然而,WebSocket的也有最严格的要求,它仅在最新版本的MicrosoftInternet Explorer、谷歌Chrome和MozillaFirefox浏览器中支持,其他浏览器如Opera和Safari中都只有部分部分实现(2014最新版本的Opera和Safari就不清楚了,估计会都支持,这是未来发展的方向)。
2)服务器发送事件:也被称为EventSource(如果浏览器支持服务器发送的事件,这基本上是除了IE外的浏览器都支持该功能。)
2.1.2Comet的传输方式:
下面的传输类型都是基于CometWeb应用程序模型的,浏览器或客户端将保持HTTP的长连接请求,服务器可以在客户端没有明确请求的情况下,将数据推送到客户端。
1)Forever Frame(仅适用于IE浏览器) :Forever Frame会创建一个隐藏的IFrame ,然后向服务器发送一个不会完成的请求。然后服务器不断地发送脚本到客户端,并且由客户端立即执行该脚本,即建立一个从服务器到客户端的单向实时连接。而从客户端到服务器的连接则使用不同于该连接的其他连接。像一个标准的HTML请求时一样,会为每次数据的发送都会创建一个新的连接。
2)Ajax长轮询:长轮询不会创建一个持久的连接,而是通过客户端不断发出对服务器端的请求来进行轮询。在每次连接时,都会等待服务器发出响应后关闭这次连接,然后再立即发出新的请求(自己也可以定义间隔时间后,再发送新的请求)。当然,这种方式会在连接关闭再重新连接之间,造成一定的延迟。
关于各种配置所支持的传输方式,请参见支持的平台(SupportedPlatforms).的详细信息。
2.1.3.传输方式选择的过程:
以下列表显示SignalR如何决定使用那种类型的传输方式进行传输:
1.如果浏览器是Internet Explorer 8或更早的版本,则使用长轮询。
2.如果配置了JSONP(即连接时,JSONP参数设置为true) ,则使用长轮询。
3.如果正在使用跨域连接(即SignalR端点和页面不在同一个域中) ,如能满足以下全部条件,则使用WebSocket:
1)该客户端支持CORS (跨域资源共享) 。具体详细信息请参阅CORSat caniuse.com。
2)该客户端支持的WebSocket
3)该服务器支持的WebSocket
如果以上三个条件,只要有一条不满足,则使用长轮询。有关跨域连接的详细信息,请参阅如何建立跨域连接。
4.如果没有配置使用JSONP和连接不跨域,则使用WebSocket,当然,前提是客户端和服务器端都支持WebStocket
5.如果客户端或服务器不支持WebSocket的,则使用服务器发送事件(EventSource)。
7.如果服务器发送事件不可用,则尝试使用ForeverFrame。
8.如果Forever Frame不可用,则使用长轮询。
(即默认使用的优先级:1.WebStocket;2.EventSource;3.Forever Frame; 4.长轮询)
您可以通过启用Hub日志记录,并在浏览器的控制台中查看您的应用程序使用哪种传输方式;要启用日志记录的话,请您先添加以下命令到客户端应用程序:
$ connection.hub.logging= true; |
・ 在IE浏览器中,按F12打开开发者工具, 点击控制台(console)标签.
・ 在Chrome浏览器, 按Ctrl+Shift+J.打开控制台(console)
通过观察控制台中的日志记录,你就能看到SignalR正在使用的传输方式。
2.1.5指定传输协议和fallback(协商转换)机制:
协商转换传输方式是需要一定的时间和客户端、服务器的资源。如果客户端的环境(浏览器类型版本等)是已知的,那么您可以在启动连接时,指定传输方式来提高性能。下面的代码片段演示如果已知客户端不支持任何其他传输协议时,直接在连接启动时就使用Ajax的长轮询作为传输方式:
connection.start({ transport: 'longPolling' }); |
如果您想要一个客户端按照特定的顺序进行传输方式的协商转换,你可以指定协商转换的顺序。下面的代码片断演示了优先尝试使用的WebSocket,如果不支持,则使用长轮询。
connection.start({ transport: ['webSockets','longPolling'] }); |
用于指定传输的字符串常量的定义如下
1) webSockets
2) forverFrame
3) serverSentEvent
4) longPolling
2.1.6.长连接(PersistentConnection)和集线器(Hubs)
该SignalR API包含两种模式去实现客户端和服务器之间的通信:长连接和集线器。
1)长连接(PersistentConnection):表示一个简单的从终端向单个、分组,或群发广播消息的简单结点。长连接API (由PersistentConnection类表示。封装在NET中的代码),让开发人员直接访问SignalR的底层通信协议。使用长连接的通信模式,并且对它API的调用,就如熟悉调用WCF(类似WebService)开发的API一样简单。
2)集线器(Hubs):是基于API但级别更高一级的通信管道,他允许客户端和服务器上互相直接调用方法。 SignalR能很巧妙地处理跨机器的调度,让客户端轻松地调用服务器端上的方法,就如同调用本地方法一样,反之亦然。对于使用过.net Remoting的开发人员来说,使用集线器通信模式去远程调用的服务器或客户端API,都是一件很容易的事情。使用集线器,您还可以在方法中使用强类型参数,并且绑定到你的Model类里。
3)架构图:下图显示了集线器、长连接与用于传输的底层技术之间的关系。
2.1.7.集线器(Hubs)是如何工作的:
当服务器端的代码调用客户端的方法时,服务器端将发送一个包含要调用(当一个对象被作为方法参数时,将倍序列化为JSON来发送)的方法的名称和参数的数据包,主动推送给客户端。然后,客户端检查接收到该方法名称,并在客户端定义的方法中进行匹配查找,如果匹配成功,则执行方法并且使用反序列化的对象作为方法参数。
您可以使用Fiddler之类的工具来监控方法的调用执行情况。下图显示了在Fiddler的日志中抓取到的一个从SignalR服务器发送到Web浏览器客户端的方法。该从集线器发起调用的方法为:MoveShapeHub,被调用的方法为:updateShape。
很明显,在这个例子中,这个M:[{xxxxxxxxx}]JSON数字里面,"H"对应的是服务器端的方法名,"M"对应的是客户端的方法名,"A"是我们要传输的参数
1)大多数应用程序应该使用集线器(Hubs)的API。
2)长连接(PersistentConnection)的 API可以在下列情况下使用:
a)需要指定实际发送的消息的格式。(自己定制消息的JSON格式)。
b)开发人员更喜欢WCF(Webservice)调用的方式,而不是.netRemoting。
c).现有程序已经使用WCF(Webservice)的方法的程序,并且计划移到植SignalR。