【ASP.net MVC | SignalR】建立RealTime的網頁(SignalR)

【ASP.net MVC】建立RealTime的網頁
之前有需要一個可以承載多人並且網頁可以即時的更新變化,過去的作法很多人是用 Ajax(Asynchronous JavaScript and XML)來實現這個功能,小弟我也不例外...,但最這個方法Server要足夠的吞吐量,也需要大量的平寬,設置的成本提高許多,萬一Server吞吐量不足,就好像我們寫DDoS 的Code攻擊自己的Server,而最近(應該有一段時間了...) 看到一個比較好的方法,SignalR這個技術,就想來試試看!
SignalR的重點是在於即時性!當伺服器端(Server)有新的資料出現時,即時向用戶端(Clinet)推送訊息

之前有需要一個可以承載多人並且網頁可以即時的更新變化,過去的作法很多人是用 Ajax(Asynchronous JavaScript and XML)來實現這個功能,小弟我也不例外...,但最這個方法Server要足夠的吞吐量,也需要大量的平寬,設置的成本提高許多,萬一Server吞吐量不足,就好像我們寫DDoS 的Code攻擊自己的Server,而最近(應該有一段時間了...) 看到一個比較好的方法,SignalR這個技術,就想來試試看!

 

SignalR的重點是在於即時性!當伺服器端(Server)有新的資料出現時,即時向用戶端(Clinet)推送訊息;SignalR使用的方法有下面四種方法:

1. Websockets:

Websocket是W3C(World Wide Web Consortium)所定義的一個HTML 5的標準API,也是一個通訊的協定。

運作方式主要是在瀏覽器(browser)中開啟一個Socket,作為Server與Clinet的雙向的通訊管道,這個通道會持續地連線,直到其中一方關閉了這個Socket。

這個方法寫作非常的方便,只需要呼叫API就可以達成,但是因為Html 5的標準還沒正式定案,支援的瀏覽器也需要非常的新(目前有支援的瀏覽器IE10, Chrome and Firefox),而我們也無法限制Clinet端的Browser的版本進入我們的網站,所以這個目前狀況下比較難以實作。

WebSocket範例程式碼:

var ws = new WebSocket("ws://localhost:9999/socket");
ws.onopen = function() {
// Web Socket is connected, send data using send() 
ws.send("Message to send");
alert("Message is sent...");
};
ws.onmessage = function(evt) {
var received_msg = evt.data;
alert("Message is received...");
};
ws.onclose = function () {
// websocket is closed.
alert("Connection is closed...");
};

2. Server-Sent Events:

這個方法也是Html 5的一個API,這個API仍處於一個草案的狀態,所以市面上也比較少人介紹這個,這個方法是利用Javascript的方式來實作,與WebSocket相比,Server-Sent Events的方式是開啟一個與Server的通道,而這個通道為單向,只接收Server端傳送的訊息,這個方法實作上會更為簡便,只需要在JavaScript建立一個接收的Socket就可以完成了!

Server-Sent Events範例:

var source = new EventSource('/getevents');
source.onmessage = function(event) {
alert(event.data);
};

3. Long polling:

而這個方法,個人認為在Html5定案前及瀏覽器版本都可以支援Html5之前,這是一個最好的使用方式,其運作原理為Browser載入網頁後,先送出一個封包,這個封包會持續等到Server端有新的資料後才做出回應,假設Clinet端要發送一筆新的訊息,則會另外在開啟一個通道傳送,而長輪詢的優點在於低延遲,在即時性網頁上目前是一個最佳的解決方案!但長輪詢缺點是消耗的資源比其他方法高,在更新上比較頻繁的網頁上,會有延遲的狀態產生。

4. Forever frame:

這個方法,個人認為不是一個很好的解決方案,其運作方式是:利用一個iframe的標籤,指定一個連接的URL位置,這個網頁要一直處於傳送的狀態中(所以稱為"永遠"...),接收來自Server的訊息,並更新原本的Html頁面資料,因為她永源連接著,所以我們可以實現將最新的資料不斷地推向Clinet端,就缺點來說,要考慮的因素較多(EX:用戶端的防火牆、附加元件...)還有長時間使用後,會占用較多的記憶體空間,所以需要進行"回收"的工作。

 

SignalR是ASP.net所提供的一種服務項目,讓以上的四種方法,可以快速的實作在專案中;Clinet及Server端透過SignalR做即時性的溝通,而開發人員不需要花費太多的時間去設計Long polling、WebSocket、Server-Sent Event…的程式碼,只需要安裝SignalR的元件,就實作我們要的功能了!

((ASP.net 的項目))

 

安裝方式也是非常的簡單,透過NuGet就可以取得!

開啟NuGet後選擇"線上"在發行版本上,請選擇:僅限穩定,在搜尋欄上輸入"Signalr",就可以看到Microsoft.ASP.net SignalR,安裝這個版本,就可以使用SignalR了!

image

利用NuGet的好處就是,會把相依需求都一併幫您下載!

image

安裝後,就可以開始寫作簡單的一個聊天室了!


聊天室實作首先,我們要在Global.asax檔案中加上一行Code

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteTable.Routes.MapHubs();//註冊 ~/signalr 路由
    RouteConfig.RegisterRoutes(RouteTable.Routes);//RouteTable.Routes.MapHubs(); 必須放置在這行之前
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

之後,我們先在專案下建立一個名為Chat.cs的檔案

將下列程式碼複製後,貼到這個CS檔案中

public class Chat : Hub
    {
        public void Hello()
        {
            Clients.All.hello();
        }

        public void Send(String Message)
        {
            Clients.All.addMessage(Message);
        }
    }

而在View的部分

<input type="text" id="message" />
<input type="button" id="sendmsg" value="送出" />
<ul id="msgbox">
    
</ul>
<script type="text/javascript">
    $(function () {
        var chat = $.connection.chat;

        chat.client.addMessage = function (message) {
            $('#msgbox').append("<li>" + message + "</li>");
        };

        $("#sendmsg").click(function () {
            chat.server.send($("#message").val());
        });
        
        $.connection.hub.start();
    });
</script>

這樣就可以執行,就是一個簡單的聊天室囉!

image

在這個Chrome的開發者模式中,可以看到其中一個項目一直處於Pending的狀態,看到這個我們就完成了SignalR 的網站囉!

下面程式碼,是小弟註解的版本,提供大家修改這個聊天室囉!

<script type="text/javascript">
    $(function () {
        //必要!建立通訊物件
        var chat = $.connection.chat;
        //接收訊息
        chat.client.addMessage = function (message) {
            $('#msgbox').append("<li>" + message + "</li>");
        };
        //傳送訊息
        $("#sendmsg").click(function () {
            chat.server.send($("#message").val());
        });
        //必須!開啟連接!
        $.connection.hub.start();
    });
</script>

 

 


 

大家好我是饅頭,希望大家喜歡我的文章

如果有錯誤的地方請不吝指教 ^_^