一. 聲明 javascript
原計劃三天更新一篇,結果週五下班前忘記提交代碼了,加上週六公司組織活動,該系列推遲一天,今天大清早跑到公司,務必也要寫完這一節,這裏分享一下昨天公司組織活動拍攝的照片。html
上面廢話說多了,下面進入正題。前端
二. SignalR簡介java
SignalR是微軟的一個開源項目,爲客戶端和服務器端實時通信的問題提供了很好的解決方案,經過簡單的配置和API調用,便可完成相應的通信功能的開發。jquery
(PS:截止目前【2018-07-08】最新版本爲 2.3.0,GitHub地址爲:https://github.com/SignalR/SignalR)git
前面一節提到已經有了WebSocket,那麼爲何還要SignalR呢?github
首先WebSocket兼容性存在問題,針對這一點,SignalR對目前爲止幾類主流的傳輸協議進行了封裝,讓瀏覽器自行選擇能夠兼容的版本(固然也能夠自行指定),這樣就解決了開發者使用WebSocket時候的痛點了。web
SignalR大一統:瀏覽器
它封裝了 WebSocket、ForeverFrame、ServerSentEvents、LongPolling四種主要的傳輸協議。服務器
① WebSocket:它是HTML5提供的一種在單個 TCP 鏈接上進行全雙工通信的協議。
② ForeverFrame(永久幀):它適用於IE瀏覽器,是在頁面中插入一個隱藏的iframe,利用其src屬性在服務器和客戶端之間建立一條長連接,服務器向iframe傳輸數據(一般是HTML,內有負責插入信息的javascript),來實時更新頁面。
③ SeverSentEvents(服務器發送事件,也成EventSourse):顧名思義。
④ longPolling(Ajax長輪詢):長輪詢是對輪詢的改進,客戶端經過請求鏈接到服務器,並保持一段時間的鏈接狀態,直到消息更新或超時才返回Response並停止鏈接,能夠有效減小無效請求的次數。
如何指定傳輸協議:
(1). 默認選擇:conn.start().done(function () {});
(2). 手動指定:conn.start({ transport: 'serverSentEvents' }).done(function () {});
注. 可選參數有:webSockets、foreverFrame、serverSentEvents、longPolling
(3). 手動指定多個,若是不兼容,依次向後選擇:conn.start({ transport: ['foreverFrame','webSockets'] }).done(function () {});
這裏簡單分享一下我這裏使用的代碼,不介紹了後面章節有詳細的介紹。
前端代碼:
1 @{ 2 Layout = null; 3 } 4 5 <!DOCTYPE html> 6 7 <html> 8 <head> 9 <meta name="viewport" content="width=device-width" /> 10 <title>Index</title> 11 <script src="~/Scripts/jquery-3.3.1.min.js"></script> 12 <script src="~/Scripts/jquery.signalR-2.3.0.js"></script> 13 <script type="text/javascript"> 14 $(function () { 15 var conn = $.connection("/myPreConnection1"); 16 //開啓日誌 17 conn.logging = true; 18 19 //1. 默認的形式選擇 20 conn.start().done(function () { 21 22 }); 23 24 //2. 手動指定通信方式 25 //webSockets、foreverFrame、serverSentEvents、longPolling 26 //conn.start({ transport: 'serverSentEvents' }).done(function () { 27 28 //}); 29 30 //3. 手動指定多個通信方式,按順序選擇(第一個不支持的話,依次日後類推) 31 //conn.start({ transport: ['foreverFrame','webSockets'] }).done(function () { 32 33 //}); 34 35 }); 36 </script> 37 </head> 38 <body> 39 <div> 40 </div> 41 </body> 42 </html>
OWIN Startup Class:
1 using System; 2 using System.Threading.Tasks; 3 using Microsoft.Owin; 4 using Owin; 5 6 [assembly: OwinStartup(typeof(SignalRDemo.Startup))] 7 8 namespace SignalRDemo 9 { 10 public class Startup 11 { 12 public void Configuration(IAppBuilder app) 13 { 14 // 有關如何配置應用程序的詳細信息,請訪問 https://go.microsoft.com/fwlink/?LinkID=316888 15 16 app.MapSignalR<MyPresitentConnection1>("/myPreConnection1"); 17 } 18 } 19 }
永久鏈接模型類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading.Tasks; 5 using System.Web; 6 using Microsoft.AspNet.SignalR; 7 8 namespace SignalRDemo 9 { 10 public class MyPresitentConnection1 : PersistentConnection 11 { 12 //下面的兩個方法OnConnected 和 OnReceived默認帶的 13 14 /// <summary> 15 /// 鏈接成功後的方法(已測試) 16 /// </summary> 17 /// <param name="request"></param> 18 /// <param name="connectionId"></param> 19 /// <returns></returns> 20 protected override Task OnConnected(IRequest request, string connectionId) 21 { 22 return Connection.Send(connectionId, "Welcome!"); 23 } 24 25 /// <summary> 26 /// 接收請求的方法(已測試) 27 /// </summary> 28 /// <param name="request"></param> 29 /// <param name="connectionId"></param> 30 /// <param name="data"></param> 31 /// <returns></returns> 32 protected override Task OnReceived(IRequest request, string connectionId, string data) 33 { 34 return Connection.Broadcast(data); 35 } 36 37 } 38 }
測試一下:
① 默認的形式
② 手動指定
能夠自行去測試不一樣瀏覽器不一樣版本兼容哪些協議,這裏就不在過多測試了。
若是不指定協議,默認選擇傳輸的協議的順序爲:
三. 兩種通信模型
SignalR客戶端和服務器端通信有兩種模型:分別是永久鏈接模型(PresistentConnection)和中心模型(Hubs),其中永久鏈接更加偏向底層,代碼編寫與原生的WebSocket很像,我我的不是很喜歡這種模式;中心模型Hubs更像面向開發者的模式,它實質上是對PresitentConnection作了封裝,使其更加友好,我的很是推薦這種模式,該模式有一個很是好的地方,它容許客戶端和服務器端自定義方法而後相互之間調用。
(1). PresistentConnection:用於單個發件人、分組、廣播消息的簡單終結點,開發人員經過使用持久性鏈接Api,直接訪問SignalR公開的底層通訊協議。
(2). Hub: 基於永久鏈接之上更高層的封裝,它容許客戶端和服務器端自定義方法而且相互調用,它還容許將強類型的參數傳遞給方法而且綁定模型。
下面能夠很好的說明這兩種模式的關係
簡單看看PresitentConnection模型的代碼和WebSocket確實有點像。
1 <script type="text/javascript"> 2 $(function () { 3 var conn = $.connection("/myPreConnection1"); 4 //1. 開啓鏈接 5 conn.start().done(function () { 6 7 }); 8 //2. 接受服務器發來的消息 9 conn.received(function (data) { 10 console.log(data); 11 }); 12 //3. 鏈接斷開的方法 13 conn.disconnected(function () { 14 $("#j_notice").html("鏈接中斷"); 15 }); 16 17 18 //斷開鏈接事件 19 $("#j_close").click(function () { 20 conn.stop(); 21 }); 22 23 //羣發事件 24 $("#j_send").click(function () { 25 conn.send("你好啊"); 26 }); 27 28 }); 29 </script>
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading.Tasks; 5 using System.Web; 6 using Microsoft.AspNet.SignalR; 7 8 namespace SignalRDemo 9 { 10 public class MyPresitentConnection1 : PersistentConnection 11 { 12 //下面的兩個方法OnConnected 和 OnReceived默認帶的 13 14 /// <summary> 15 /// 鏈接成功後的方法(已測試) 16 /// </summary> 17 /// <param name="request"></param> 18 /// <param name="connectionId"></param> 19 /// <returns></returns> 20 protected override Task OnConnected(IRequest request, string connectionId) 21 { 22 return Connection.Send(connectionId, "Welcome!"); 23 } 24 25 /// <summary> 26 /// 接收請求的方法(已測試) 27 /// </summary> 28 /// <param name="request"></param> 29 /// <param name="connectionId"></param> 30 /// <param name="data"></param> 31 /// <returns></returns> 32 protected override Task OnReceived(IRequest request, string connectionId, string data) 33 { 34 return Connection.Broadcast(data); 35 } 36 37 /// <summary> 38 /// 鏈接中斷調用方法(已測試) 39 /// </summary> 40 /// <param name="request"></param> 41 /// <param name="connectionId"></param> 42 /// <param name="stopCalled"></param> 43 /// <returns></returns> 44 protected override Task OnDisconnected(IRequest request, string connectionId, bool stopCalled) 45 { 46 return base.OnDisconnected(request, connectionId, stopCalled); 47 } 48 49 /// <summary> 50 /// 當鏈接在超時後從新鏈接時調用該方法 51 /// </summary> 52 /// <param name="request"></param> 53 /// <param name="connectionId"></param> 54 /// <returns></returns> 55 protected override Task OnReconnected(IRequest request, string connectionId) 56 { 57 return base.OnReconnected(request, connectionId); 58 } 59 } 60 }
四. 一些環境的要求
1. .Net Framework的版本
SignalR 2 起僅支持在 .Net FrameWork 4.5及以上。
2. 操做系統
Win七、Win八、Win十、WinServer 2008 R二、WinServer 20十二、WinServer 2016.
注:若是SignalR使用WebSocket協議,須要配置啓動Web套接字。
3. IIS版本
首先IIS必須使用集成模式,不支持經典模式,另外若是SignalR使用WebSocket協議的話,必須使用IIS8及以上。
注:程序必須在徹底信任的模式下運行。
4. web瀏覽器對傳輸協議的要求
首先配合使用的JQuery版本需在 1.6.4 及以上。
5. 桌面程序對傳輸協議的要求
該節到此結束,寫了大約兩個小時,下一個章節開始擼代碼,先介紹PresistentConnection這種模式,大約下週二(2018-7-10)更新,感興趣的朋友能夠關注一下,相互學習。
!