HTTP協議是一個典型的Request/Response協議,是基于TCP/ip之上的一個應用層協議,該協議最典型的特點就是無狀態且需要客戶端發起Request服務端才能進行Response,這意味著服務端無法主動“推送”信息。但現代很多應用需求這種“服務端推送”,比如說監控系統、報價系統、游戲、協同文檔、進度條等應用。因此本文會談論服務器推送技術的不同手段,以及在asp.net中的SignalR是如何封裝這些細節來達到推送的目的。
由于HTTP協議并不支持全雙工,因此目前對于服務器“推送”的手段也是根據HTTP協議的特性玩了很多小花招。但大體上可以分為高端大氣的全雙工類和略微tricky的長輪詢類。Streaming類通常會有比較多的限制,比如說對瀏覽器的版本要求、需要使用sliverlight或Flash等查件來實現全雙工等。長輪詢類主要是包括長輪詢或不間斷Ajax請求等。
Ajax定期請求方式
這種方式嚴格來說并不算是服務器推送,而是客戶端在一個比較短的間隔內定期去服務器用Ajax請求信息,如果服務器端有了新的事件,則客戶端在下一次請求就會獲取到,并在客戶端調用對應的回調函數來處理這些信息。簡單的示意圖如圖1所示。
圖1.Ajax定期請求
當然,這種方式的一些缺點也是顯而易見的,首先定期發起請求會白白消耗服務器資源,其次,這種方式也并不是真正的“實時”。
長連接的方式
長連接是另一種方式,是對于頁面掛起一個額外的Ajax請求,當服務器有事件發生時,將請求返回給客戶端,并在此掛起一個長連接。從而避免了定期請求的損耗,如圖2所示。
圖2.長連接方式
這種方式的缺點同樣顯而易見,就是需要客戶端和服務器對于這部分功能寫自定義實現代碼。
使用插件方式
使用諸如silverlight和flash等插件可以基于socket做全雙工的通信,但這種方式需要特定的客戶端,跨平臺性并不好(比如手機客戶端等不支持一些插件,PC端沒有預裝Silverlight等)。對條件限制比較嚴格。
Forever iFrame
這種方式本質上和長連接的方法非常類似,就是在頁面中嵌入一個iframe元素,該元素的Src屬性指向被請求的對象,服務端有事件發生就,就回傳一個調用客戶端JS方法的JS。Iframe中HTTP頭的Transfer-Encoding屬性為chunked,這意味著服務端并不知道要發送給客戶端多少數據,也就隱式意味著該連接的長度為無限。
HTML5 Web Socket
WebSocket是HTML5開始提供的一種瀏覽器與服務器間進行全雙工通訊的網絡技術。 WebSocket通信協議于2011年被IETF定為標準 RFC 6455,WebSocketAPI被W3C定為標準。
在WebSocket API中,瀏覽器和服務器只需要做一個握手的動作,然后,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數據互相傳送。
WebSocket協議的出現可以避免上述幾種方式帶來的服務器資源占用和寬帶占用。但缺點也是很明顯的,對客戶端和服務端都有一定要求,包括瀏覽器的版本和服務器的版本(比如IIS7.5+)
上面說到了這么多中實現實時應用程序的辦法,作為Asp.net框架中,提供了一個叫SignalR的框架來封裝這些網絡細節,SignalR會自動選擇合適的實現技術來實現該種實時程序。我們只要關注更高層面的業務實現,而無需關注技術上的實現細節。
SignalR最低需要基于Jquery 1.6.4,在服務端至少需要是.Net FrameWork 4.0+。
使用SignalR會自動根據環境選擇合適的網絡實現細節,該過程根據微軟的官網定義如下:
SignalR的實現可以通過在Visual Studio的nuget來獲取。SignalR從使用的角度來說模型非常簡單,服務端是客戶端回調用的HUB方法,而客戶端只要引入了對應的JS之后,形成Hub-PRoxy,使得服務端被調用后里的方法也可以回調不同的客戶端。模型概念如圖3所示。
圖3.SignalR的Hub模型
在服務端的Hub被調用后,我們可以處理該部分代碼,并針對不同的客戶端返回信息,一個典型的代碼如圖4所示。
圖4.一些返回給不同客戶端的方法
而在客戶端,我們僅僅需要引用SignalR的Js文件后,聲明了Hub-Proxy,就可以直接調用服務器方法,如圖5所示。
圖5.客戶端直接調用服務端的方法
我們注意到,在使用SignalR的過程中,并沒有任何關于網絡交互技術細節的實現,僅僅是簡單的調用。SignalR已經按照本文之前所提到的那樣,根據Context選擇的具體的實現細節。
新聞熱點
疑難解答