Asp.net SignalR 實現服務端消息推送到Web端

原文:http://www.cnblogs.com/wintersun/p/4148223.htmljavascript


 以前的文章介紹過Asp.net SignalR,  ASP .NET SignalR是一個ASP .NET 下的類庫,能夠在ASP .NET 的Web項目中實現實時通訊.  今天咱們來實現服務端消息推送到Web端,   首先回顧一下它抽象層次圖是這樣的:css

image

實際上 Asp.net SignalR 2 實現 服務端消息推送到Web端, 更加簡單. 爲了獲取更好的可伸縮性, 咱們引入消息隊列, 看以下基本流程圖:html

image

消息隊列MQ監聽, 在Web site 服務端一收到消息,立刻經過Signalr 推送廣播到客戶端.  建立ASP.NET MVC WEB APP,  從NuGet 安裝SignalR 2.12java

Install-Package Microsoft.AspNet.SignalRjquery

具體實現代碼,是這樣的,咱們增長一個空的Hub:git

    {
        {
    }
 

是簡單的消息模型, 標題與正文屬性: 
github

    public class PushMessageModel
        public int Id { get; set; }
        public string MSG_TITLE { get; set; }
        public string MSG_CONTENT { get; set; }

服務端推送具體類,記錄日誌, 建立消息隊列實例,監聽, 等待收取消息. 這裏咱們使用的是AcitveMQ的.net客戶端. ActiveMQListenAdapter是一個封裝過的對象. web

    {
        private static ILogger log = new Logger("MQHubsConfig");
 
        /// <summary>
        /// </summary>
        {
            var activemq = Megadotnet.MessageMQ.Adapter.ActiveMQListenAdapter<PushMessageModel>.Instance(MQConfig.MQIpAddress, MQConfig.QueueDestination);
            activemq.MQListener += m =>
                log.InfoFormat("從MQ收到消息{0}", m.MSG_CONTENT);
                GlobalHost.ConnectionManager.GetHubContext<FeedHub>().Clients.All.receive(m);
            };
 
            activemq.ReceviceListener<PushMessageModel>();
    }
 
  

上面有一句關鍵代碼GlobalHost.ConnectionManager.GetHubContext<FeedHub>().Clients.All.receive(m);  這裏使用了GetHubContext方法後,直接來廣播消息.ajax

須要在MVCApplication下加載:apache

    {
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            MQHubsConfig.RegisterMQListenAndHubs();
    }


同時須要增長一個Starup.cs, 用於Owin

namespace RealTimeApp
    public class Startup
        public void Configuration(IAppBuilder app)
            // Any connection or hub wire up and configuration should go here
            app.MapSignalR();
    }
    var init = function () {
        Feed();
        $.connection.hub.logging = true;
            .done(function() {
                console.log("Connected!");
                $(document).trigger("Connected");
            .fail(function() { console.log("Could not Connect!"); });
    };
 
    init();
};

Feed.js 具體與SignalR.js通訊, 建立名爲receive的function, 與服務端對應

    var chat = undefined;
 
    
        chat = $.connection.feedHub;
        chat.client.receive = function (item) {
            var selector = "ul.feed-list li[data-id=" + item.Id + "]";
            if (!($(selector).length > 0)) {
                $("ul.feed-list").prepend($(".feed-template").render(item));
                $("ul.feed-list li:gt(3)").remove();
 
                title: 'Tips',
                showType: 'show'          
            });
 
        };
 
        $.connection.hub.start().done(function () {
            chat.server.init();
        });
 
    };
 
    init();
};

        上面的javascript代碼與服務端有通訊, 具體看以下圖:

        image

        在Index.cshtml,  咱們須要引用SignalR客戶端JS, 放置hubs, 這裏咱們使用了jsrender,  easyui.js 來呈現推送的消息.

 
<link href="/Content/themes/default/window.css" rel="stylesheet" />
link href="~/Content/themes/default/progressbar.css" rel="stylesheet" />
link href="~/Content/themes/default/linkbutton.css" rel="stylesheet" />
script src="~/Scripts/jquery.signalR-2.1.2.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
"~/signalr/hubs"></script>
 
"~/Scripts/jsrender.js"></script>
"~/Scripts/jquery.easyui.min-1.4.1.js"></script>
 
 
"text/javascript">
            var app = new App();
        });
 
script>
 
 
class="row-fluid">
 
class="span8">
class="widget">
class="widget-header">
                <h2>Feed</h2>
            </div>
class="widget-content">
class="span12 feed-list"></ul>
            </div>
        </div>
    </div>
</div>
 
class="chat-template" type="text/x-jquery-tmpl">
    <li>
        <p>{{>Message}}</p>
    </li>
script>
 
class="feed-template" type="text/x-jquery-tmpl">
"{{>Id}}">
class="row-fluid">
 
class="span8">
                <h3>{{>MSG_CONTENT}}</h3>
            </div>
        </div>
    </li>
script>

上代碼服務端引用js的Script.Render, 須要在BundleConfig.cs中加入如下代碼:

          bundles.Add(new ScriptBundle("~/Scripts/project.js") .IncludeDirectory("~/Scripts/Project", "*.js", false));

同時咱們構建一個WebAPI來發送須要推送的消息, 片段代碼:

        /// <summary>
        /// </summary>
 
 
        /// <returns></returns>
        public IHttpActionResult SendMessage(PushMessageModel messagemodel)
            return SendToServer(messagemodel);
 
 
        /// <summary>
        /// </summary>
 
 
        /// <returns></returns>
        {
 
            {
                {
                    log.Debug("發送成功!");
                    return Ok();
                else
                    log.ErrorFormat("發送失敗!{0}", messagemodel);
                    return Content(HttpStatusCode.ExpectationFailed, new Exception("send message error"));
            }
            {
                log.ErrorFormat("參數驗證失敗!{0}", messagemodel);
                return Content(HttpStatusCode.BadRequest, ModelState);
 
 

發送消息到ActiveMQ的關鍵代碼:

    {
        private static ILogger log = new Logger("MessageRepository");
 
        /// <summary>
        /// </summary>
 
 
        /// <returns></returns>
        {
          var activemq = new ActiveMQAdapter<PushMessageModel>(MQConfig.MQIpAddress, MQConfig.QueueDestination);
          return activemq.SendMessage<PushMessageModel>(messagemodel)>0;
    }

 

若是您須要運行DEMO程序,須要構建基於ActiveMQ的消息隊列,   運行效果是這樣的, 咱們在一個靜態html中, 發送一個ajax到webapi服務端,  發送後

image

另外一個website網站收到後, 列表更新, 並在右下角彈出框

image

IE的控制檯輸出:

HTML1300: Navigation occurred. 
File: Index 
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Client subscribed to hub 'feedhub'. 
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Negotiating with '/signalr/negotiate?clientProtocol=1.4&connectionData=%5B%7B%22name%22%3A%22feedhub%22%7D%5D'. 
[11:05:25 GMT+0800 (China Standard Time)] SignalR: This browser doesn't support SSE. 
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Binding to iframe's load event. 
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Iframe transport started. 
[11:05:25 GMT+0800 (China Standard Time)] SignalR: foreverFrame transport selected. Initiating start request. 
[11:05:25 GMT+0800 (China Standard Time)] SignalR: The start request succeeded. Transitioning to the connected state. 
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Now monitoring keep alive with a warning timeout of 13333.333333333332 and a connection lost timeout of 20000. 
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Invoking feedhub.Init 
Connected! 
[11:05:25 GMT+0800 (China Standard Time)] SignalR: Invoked feedhub.Init 
[11:07:12 GMT+0800 (China Standard Time)] SignalR: Triggering client hub event 'receive' on hub 'FeedHub'. 
[11:07:18 GMT+0800 (China Standard Time)] SignalR: Triggering client hub event 'receive' on hub 'FeedHub'. 
[11:07:32 GMT+0800 (China Standard Time)] SignalR: Triggering client hub event 'receive' on hub 'FeedHub'. 
[11:07:51 GMT+0800 (China Standard Time)] SignalR: Triggering client hub event 'receive' on hub 'FeedHub'. 
[11:09:25 GMT+0800 (China Standard Time)] SignalR: Triggering client hub event 'receive' on hub 'FeedHub'.

上面粗體是 最後咱們發的第5條信息控制檯的輸出.

 

好了,到這兒, 因爲篇幅有限, 示例代碼沒有所有展現, 能夠在這兒下載,  須要安裝ActiveMQ

相關文章
相關標籤/搜索