ASP.NET SignalR 技術出來好幾年了,一直沒有為它發個文,網路上也有很多相關的文章,大家 Google 一下就很多了,我參考了黑大的文章,而黑大的文章裡面也有連結到其他兩位專家的文章,大家可以去看看,我這邊僅記錄自己實作過程及心得。
ASP.NET SignalR 基本運作概念
SignalR 是集中式的架構,訊息的傳遞由伺服器提供的集中器(Hub)
統一處理,在 Hub 中需要宣告給客戶端呼叫的方法,而客戶端需要至少指定一個 Hub 並為指定的 Hub 建立 Proxy,而且也要宣告給伺服器端呼叫的方法,完成之後進行連線,兩邊就透過呼叫彼此的方法進行溝通。
客戶端與客戶端之間彼此要溝通,需要指定同一個 Hub,將訊息透過 Hub 提供的方法傳送到 Hub 上,由 Hub 決定要將訊息往外傳遞給哪些客戶端,客戶端之間借助這樣的路由機制就可以溝通了。
放在伺服器端 Hub 上給客戶端呼叫的方法及放在客戶端 Hub Proxy 上給伺服器端呼叫的方法,方法名稱不一定要一樣,只要呼叫的時候方法名稱不要打錯、參數的數量要給對就可以了。
架設 SignalR 伺服器
既然是 ASP.NET SignalR 當然我們就要建立一個 ASP.NET 的專案,我這邊是用 ASP.NET Web Application (.NET Framework) 這個專案範本建立一個 ASP.NET MVC 的空白專案。
為了方便測試,我建立了一個發送訊息的介面,有 Name 及 Message 欄位。
接著我們到 NuGet 安裝 Microsoft.AspNet.SignalR 套件。
Microsoft.AspNet.SignalR 安裝好之後,我們要先建立一個 Hub,名字就叫 BroadcastHub
,裡面就宣告一個給客戶端呼叫的方法 Broadcast(string name, string message)
,方法裡面我要去呼叫所有客戶端的 showmessage
方法,參數是 name
及 message
。
public class BroadcastHub : Hub
{
public void Broadcast(string name, string message)
{
Clients.All.showmessage(name, message);
}
}
最後建立一個 Startup
把它註冊在 OwinStartup
,伺服器的部分大致上就準備完成了。
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(AspNetSignalRSamples.SignalR.Startup))]
namespace AspNetSignalRSamples.SignalR
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
實作 SignalR Web 客戶端
關於 SignalR 客戶端的部分,如果我們可以找到相對應的 SignalR Client Api,我們就可以來操作 SignalR 技術,我這邊只介紹 Web 跟 Windows,其他的就留待大家自行發掘。
SignalR 的 Web Client 我們可以引入 jquery.signalR-x.x.x.js
這個 js 檔來實現,引入之後首要第一件事就是建立 Hub Proxy,客戶端建立 Hub Proxy 有兩種方法。
With the generated proxy
SignalR 的伺服器端 Web Site 預設會提供一個 /signalr/hubs
Web Api,裡面其實是一堆指令碼,它是由 SignalR 自己自動產生的 Hub Proxy Script,只要引用它就有 Hub Proxy 可以用,不用自己辛苦建立。
<script src="~/Scripts/jquery.signalR-2.2.0.js"></script>
<script src="~/signalr/hubs"></script>
<script>
$(function () {
// Create Hub Proxy
var broadcastHub = $.connection.broadcastHub;
// ToDo: 註冊給伺服器端呼叫的方法
$.connection.hub.start()
.done(function () {
// ToDo: 與伺服器連線註冊成功後要執行的作業
});
});
</script>
Without the generated proxy
如果我們不引用 Hub Proxy Script,就要自己寫 Code 建立,其實也沒有多打多少程式碼。
<script src="~/Scripts/jquery.signalR-2.2.0.js"></script>
<script>
$(function () {
// Create Hub Proxy
var connection = $.hubConnection();
var broadcastHub = connection.createHubProxy('broadcastHub');
// ToDo: 註冊給伺服器端呼叫的方法
connection.start()
.done(function () {
// ToDo: 與伺服器連線註冊成功後要執行的作業
});
});
</script>
何時該用 Without the generated proxy 的方式?
差別在於如果你要用同一個客戶端方法,執行不同的事件處理,就必須得用 Without the generated proxy 的方式。
舉例來講,我在客戶端宣告兩個給伺服器端呼叫的 hello
多載方法,一個要把訊息顯示在網頁上,一個要跳出 alert 視窗,兩個 hello 方法的參數個數也不一樣,如果用 With the generated proxy 的方式,就只會認得最後註冊的那一個,前面不管註冊多少多載方法都沒有用。
<script src="~/Scripts/jquery.signalR-2.2.0.js"></script>
<script>
$(function () {
// ToDo: Create Hub Proxy
broadcastHub.on('hello', function (name) {
$('#messages').append('<li><strong>' + htmlEncode(name) + '</strong>: ' + htmlEncode(message) + '</li>');
});
broadcastHub.on('hello', function (name, age) {
alert(name + ', ' + age);
});
// ToDo: Start Connection
});
</script>
而對於伺服器來講只要呼叫最多參數的那個 hello 方法就可以了。
public class HelloHub : Hub
{
public void Hello()
{
Clients.All.hello("Johnny", 28);
}
}
不過要自己寫 Code 產生 Hub Proxy 的情境比較少,所以我們預設還是優先選擇引用 SignalR 幫我們產生的 Hub Proxy Script,無法滿足的時候再考慮用另外一個方法。
建立完 Hub Proxy 之後,接著註冊給伺服端呼叫的方法、連線到 SignalR 伺服器、註冊連線成功後要執行的作業,就完成了。
<script src="~/Scripts/jquery.signalR-2.2.0.js"></script>
<script src="~/signalr/hubs"></script>
<script>
$(function () {
// With the generated proxy
// Create Hub Proxy
var broadcastHub = $.connection.broadcastHub;
// 註冊給伺服端呼叫的方法
broadcastHub.client.showmessage = function (name, message) {
$('#messages').append('<li><strong>' + htmlEncode(name) + '</strong>: ' + htmlEncode(message) + '</li>');
};
// 連線到 SignalR 伺服器
$.connection.hub.start()
.done(function () {
// 註冊連線成功後要執行的作業
$('#sendmessage').click(function () {
broadcastHub.server.broadcast($('#name').val(), $('#message').val());
});
});
});
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script>
實作 SignalR Windows 客戶端
Windows 客戶端的部分我們可以仰賴 Microsoft.AspNet.SignalR.Client 套件,安裝好之後做法跟 Web Client 是差不多的,建立 Hub Proxy、註冊給伺服端呼叫的方法、連線到 SignalR 伺服器。
各位觀眾!!!…三方會談!!!
參考資料
< Source Code >