用SignalR建立實時永久長連線非同步網路應用程式
我最近在研究非同步和衡量的問題。你可能看過我之前寫的博文:我研究的 node.js和iisnode在Windows上執行。
每個應用程式都有不同的要求,“衡量”的規則不是對每一種應用程式都適用的。衡量一個獲取資料和迴圈的網路應用和那些召集深度潛在的主框架應用,保持伺服器永久連線的應用是不一樣的。
古語說“當你手上只有榔頭的時候,看什麼都像是釘子”,這個在程式設計和網路世界裡的確是真理。工具越多並且掌握使用它們的技能那麼效果就會越好。那也是為什麼我不僅僅宣揚多種語言程式設計,還希望大家深入研究自己的主要語言。比如當你真正學會了LINQ,並且很擅長使用dynamic,C#就變成了一種更加有趣和富有表現力的語言。
更新是用榔頭錘釘子的常見例子。想做一個聊天程式?每隔5秒更新一次。處理時間很長?那就丟掉動畫圖片,不停地更新,我親愛的朋友!
間隔長一段時間來更新是另一種方法。簡單來說就是開啟一個連線然後保持開啟狀態,強制客戶端(瀏覽器)等待,假裝需要很長時間才能返回結果。如果你的伺服器端程式模型上有足夠多的控制元件,這就能允許你按照你期望的來返回資料在開啟的連線上。如果連線斷開了,連線會無縫地被重新開啟,斷開資訊會在兩個埠都隱藏掉。在WebSockets將會是另一種解決這類問題的方法。
ASP.NET中的永恆連線
在聊天應用程式或者股票應用程式中用ASP.NET做這樣的永久連線不是很容易。在伺服器或客戶庫中還沒有一個合適的概念來討論它。
SignalR是為ASP.NET而設的一個非同步訊號庫。我們團隊正在研究這個專案,希望能建立實時的多使用者網路應用。
這不就是Socket.IO或者nowjs麼?
Socket.IO是一個客戶端JavaScript庫,能與node.js進行交流。Nowjs是能讓你從伺服器端呼叫客戶的類庫。這些和Signalr都很相似而且相關,只是同一個概念中的不同方面。這些JavaScript庫都希望在伺服器端有特定的東西和協定,這樣就有可能讓伺服器端的顯示如同客戶希望看到的那樣。
SignalR是一個完全基於客戶及伺服器端解決方案,它是以JS作為客戶端和ASP.NET作為服務端來建立這類的應用。你可以去GitHub獲取。
我能用12行程式碼建立一個聊天應用嗎?
我想說
“在程式碼的世界中,簡潔明瞭永遠不是神話。”
換句話說,我希望我能這麼說,當然可以!
1: Chat.DoItBaby()
但是那可能是一個謊言,下面是SignalR中的一個真實的聊天應用程式例子:
客戶:
1: var chat = $.connection.chat;
2: chat.name = prompt("What's your name?", "");
3:
4: chat.receive = function(name, message){
5: $("#messages").append(""+name+": "+message);
6: }
7:
8: $("#send-button").click(function(){
9: chat.distribute($("#text-input").val());
10: });
伺服器:
1: public class Chat : Hub {
2: public void Distribute(string message) {
3: Clients.receive(Caller.name, message);
4: }
5: }
那也許是12行,其實可以縮到9行的,如果你願意的話。
有關SignalR的更多細節
SignalR在NuGet上被分成了幾個包:
· SignalR – 主要的包,包括SignalR.Server和SignalR.Js(你應該安裝這個)
· SignalR.Server – 伺服器端元件用以建立SignalR端點
· SignalR.Js – SignalR的Javascript客戶端
· SignalR.Client – SignalR的.NET客戶端
· SignalR.Ninject - SignalR 的Ninject 相關解決方案
如果你只是想了解一下玩一玩,那就從Visual Studio 2010開始。
首先,建立一個空白的ASP.NET應用程式,用NuGet安裝SignalR包,用NuGet的UI或者Package Console都可以。
其次,建立一個新的default.aspx頁面,新增一個按鈕,一個文字框,用以下指令碼來引用jQuery和jQuery.signalR。
1: <html >
2: <head runat="server">
3: <script src="Scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
4: <script src="Scripts/jquery.signalR.min.js" type="text/javascript"></script>
5: </head>
6: <body>
7: <form id="form1" runat="server">
8: <div>
9: <script type="text/javascript">
10: $(function () {
11: var connection = $.connection('echo');
12: connection.received(function (data) {
13: $('#messages').append('<li>' + data + '</li>');
14: });
15: connection.start();
16: $("#broadcast").click(function () {
17: connection.send($('#msg').val());
18: });
19: });
20: </script>
21: <input type="text" id="msg" />
22: <input type="button" id="broadcast" />
23: <ul id="messages"></ul>
24: </div>
25: </form>
26: </body>
27: </html>
底層連線
注意我們是從客戶端呼叫/echo嗎?這個在Global.asax中有所介紹:
1: RouteTable.Routes.MapConnection<MyConnection>("echo", "echo/{*operation}");
現在,我們��兩個SignalR模型來選擇。我們先來看看底層的這個。
1: using SignalR;
2: using System.Threading.Tasks;
3:
4: public class MyConnection : PersistentConnection
5: {
6: protected override Task OnReceivedAsync(string clientId, string data)
7: {
8: // Broadcast data to all clients
9: return Connection.Broadcast(data);
10: }
11: }
我們繼承PersistentConnection這個類,基本上可以在這層中做我們想做的任何事,這有很多個選擇:
1: public abstract class PersistentConnection : HttpTaskAsyncHandler, IGroupManager
2: {
3: protected ITransport _transport;
4:
5: protected PersistentConnection();
6: protected PersistentConnection(Signaler signaler, IMessageStore store, IJsonStringifier jsonStringifier);
7:
8: public IConnection Connection { get; }
9: public override bool IsReusable { get; }
10:
11: public void AddToGroup(string clientId, string groupName);
12: protected virtual IConnection CreateConnection(string clientId, IEnumerable<string> groups, HttpContextBase context);
13: protected virtual void OnConnected(HttpContextBase context, string clientId);
14: protected virtual Task OnConnectedAsync(HttpContextBase context, string clientId);
15: protected virtual void OnDisconnect(string clientId);
16: protected virtual Task OnDisconnectAsync(string clientId);
17: protected virtual void OnError(Exception e);
18: protected virtual Task OnErrorAsync(Exception e);
19: protected virtual void OnReceived(string clientId, string data);
20: protected virtual Task OnReceivedAsync(string clientId, string data);
21: public override Task ProcessRequestAsync(HttpContext context);
22: public void RemoveFromGroup(string clientId, string groupName);
23: public void Send(object value);
24: public void Send(string clientId, object value);
25: public void SendToGroup(string groupName, object value);
26: }
高階中轉站
或者我們可以提高一級,在新增
<script src="http://blogs.msdn.com/signalr/hubs" type="text/javascript"></script>
至頁面後為我們的聊天客戶做這個:
1: $(function () {
2: // Proxy created on the fly
3: var chat = $.connection.chat;
4:
5: // Declare a function on the chat hub so the server can invoke it
6: chat.addMessage = function (message) {
7: $('#messages').append('<li>' + message + '</li>');
8: };
9:
10: $("#broadcast").click(function () {
11: // Call the chat method on the server
12: chat.send($('#msg').val());
13: });
14:
15: // Start the connection
16: $.connection.hub.start();
17: });
然後就沒有跟蹤的必要了,連線聊天會對映到伺服器上,然後伺服器就能回撥客戶端了。
1: public class Chat : Hub
2: {
3: public void Send(string message)
4: {
5: // Call the addMessage method on all clients
6: Clients.addMessage(message);
7: }
8: }
我想你的腦子到現在應該要炸了。這是C#,伺服器端程式碼,我們告訴所有的客戶呼叫addMessage() JavaScript函式。我們通過永久連線,傳送客戶函式名稱以獲得伺服器端回應,從而回撥客戶端。這和NowJS很像,但是沒有很多人熟悉這個技術。
SignalR會處理所有客戶端和伺服器端的連線,確保它保持連線,執行正常。它會為你的瀏覽器選擇正確的連線方式,用非同步衡量async,await技術(就像我在node.js博文中展示過的asp.net上的可衡量非同步事件 I/O )。
想親眼看看這個樣本的執行?
我們在http://chatapp.apphb.com上有一個小小的聊天應用程式,快去看看吧。那裡有aspnet的同仁。試試貼上到你的YouTube或相簿上吧!
這是早期的,不過還是一個很有趣的.NET新元件,以前也從沒出現過。你可以隨意去GitHub看看,和SignalR的作者David Fowler和Damian Edwards交流下。希望你們喜歡。
相關文章
- 實時web應用方案——SignalR(.net core)WebSignalR
- HMS Core網路加速套件:hQUIC Kit為應用快速建立網路連線套件UI
- SignalR2 永久連線簡單例項1SignalR單例
- Data Guard備庫日誌的實時應用與非實時應用
- 應用連線超時排查DB MySQLMySql
- 使用SignalR構建聊天應用程式SignalR
- 用社交網路連線 WebSphere MQ:列隊管理器和 MQ 應用程式的 Twitter 通知WebMQ
- 2.3.6 應用程式同步
- 建立安全PHP應用程式的實用建議PHP
- 【JDBC】使用OracleDataSource建立連線池用於連線OracleJDBCOracle
- 應用JDBC連線SQLiteJDBCSQLite
- 菜鳥學網路之 —— 長連線和短連線
- 解決win10應用商店未連線網路的最佳方法Win10
- 使用goldengate時,絕對禁止前臺應用程式連線目的庫Go
- 物聯網應用的蜂窩eSIM連線
- 輕鬆應用Linux連線校園網Linux
- python網路爬蟲應用_python網路爬蟲應用實戰Python爬蟲
- P2P網路被谷歌用來共享離線安裝應用程式谷歌
- 從同步原語看非阻塞同步以及Java中的應用Java
- MFC開發(一)簡單同步時間應用程式
- not in 用外連線實現
- 應用響應時延背後 深藏的網路時延
- 網路連線為何無法停用和啟用?
- IIS連線數、併發連線數、最大併發工作執行緒數、應用程式池的佇列長度、應用程式池的最大工作程式數詳解執行緒佇列
- 連線網際網路—碰到我16歲時建立已有15年之久的網站網站
- 無線網路應用配置六步走
- 長連線資料實時推送方案(iOS)iOS
- windows10應用商店無法聯網怎麼辦_win10應用商店無法連線網路如何解決WindowsWin10
- 【問題記錄】—SignalR連線斷線重連SignalR
- DataGuard實時應用
- 網路應用優化——時延與頻寬優化
- 【實操】小程式的應用場景分析——線下場景應用
- 建立Java的應用程式(轉)Java
- IntelliJIDEA最常用配置,應用、永久啟用IntelliJIdea
- Exhibeo 2 for Mac(網路相簿應用程式)Mac
- Linux 上用 IP轉發使內部網路連線到網際網路Linux
- 2.3.6.1 單個應用程式的同步
- 企業無線網路安全應用解決方案