第一章ASP.NET SignalR簡介
1.1概述:
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的也有最嚴格的要求,它僅在最新版本的Microsoft Internet Explorer、谷歌Chrome和Mozilla Firefox瀏覽器中支持,其他瀏覽器如Opera和Safari中都只有部分部分實現(2014最新版本的Opera和Safari就不清楚了,估計會都支持,這是未來發展的方向)。
2)服務器發送事件:也被稱為EventSource(如果瀏覽器支持服務器發送的事件,這基本上是除了IE外的瀏覽器都支持該功能。)
2.1.2 Comet的傳輸方式:
下面的傳輸類型都是基於Comet Web應用程序模型的,瀏覽器或客戶端將保持HTTP的長連接請求,服務器可以在客戶端沒有明確請求的情況下,將數據推送到客戶端。
1)Forever Frame(僅適用於IE瀏覽器) :Forever Frame會創建一個隱藏的IFrame ,然后向服務器發送一個不會完成的請求。然后服務器不斷地發送腳本到客戶端,並且由客戶端立即執行該腳本,即建立一個從服務器到客戶端的單向實時連接。而從客戶端到服務器的連接則使用不同於該連接的其他連接。像一個標准的HTML請求時一樣,會為每次數據的發送都會創建一個新的連接。
2)Ajax長輪詢:長輪詢不會創建一個持久的連接,而是通過客戶端不斷發出對服務器端的請求來進行輪詢。在每次連接時,都會等待服務器發出響應后關閉這次連接,然后再立即發出新的請求(自己也可以定義間隔時間后,再發送新的請求)。當然,這種方式會在連接關閉再重新連接之間,造成一定的延遲。
關於各種配置所支持的傳輸方式,請參見支持的平台(Supported Platforms).的詳細信息。
2.1.3.傳輸方式選擇的過程:
以下列表顯示SignalR如何決定使用那種類型的傳輸方式進行傳輸:
1.如果瀏覽器是Internet Explorer 8或更早的版本,則使用長輪詢。
2.如果配置了JSONP(即連接時,JSONP參數設置為true) ,則使用長輪詢。
3.如果正在使用跨域連接(即SignalR端點和頁面不在同一個域中) ,如能滿足以下全部條件,則使用WebSocket:
1)該客戶端支持CORS (跨域資源共享) 。具體詳細信息請參閱CORS at caniuse.com 。
2)該客戶端支持的WebSocket
3)該服務器支持的WebSocket
如果以上三個條件,只要有一條不滿足,則使用長輪詢。有關跨域連接的詳細信息,請參閱如何建立跨域連接。
4.如果沒有配置使用JSONP和連接不跨域,則使用WebSocket,當然,前提是客戶端和服務器端都支持WebStocket
5.如果客戶端或服務器不支持WebSocket的,則使用服務器發送事件(EventSource)。
7.如果服務器發送事件不可用,則嘗試使用Forever Frame。
8.如果Forever Frame不可用,則使用長輪詢。
(即默認使用的優先級:1.WebStocket;2.EventSource;3.Forever Frame; 4.長輪詢)
2.1.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"是我們要傳輸的參數
2.1.8 長連接(PersistentConnection)和集線器(Hubs)的選擇(通信模式的選擇):
1)大多數應用程序應該使用集線器(Hubs)的API。
2)長連接(PersistentConnection)的 API可以在下列情況下使用:
a)需要指定實際發送的消息的格式。(自己定制消息的JSON格式)。
b)開發人員更喜歡WCF(Webservice)調用的方式,而不是.net Remoting。
c).現有程序已經使用WCF(Webservice)的方法的程序,並且計划移到植SignalR。