您的位置:首页 > 编程语言 > ASP

Asp.net SignalR 实现服务端消息推送到Web端

2016-08-23 16:50 806 查看
之前的文章介绍过Asp.netSignalR,ASP.NETSignalR是一个ASP.NET下的类库,可以在ASP.NET的Web项目中实现实时通信.今天我们来实现服务端消息推送到Web端,首先回顾一下它抽象层次图是这样的:






实际上Asp.netSignalR2实现服务端消息推送到Web端,更加简单.为了获取更好的可伸缩性,我们引入消息队列,看如下基本流程图:





消息队列MQ监听,在Website服务端一收到消息,马上通过Signalr推送广播到客户端.创建ASP.NETMVCWEBAPP,从NuGet安装SignalR2.12

Install-PackageMicrosoft.AspNet.SignalR

具体实现代码,是这样的,我们增加一个空的Hub:

publicclassFeedHub:Hub

[code]{
publicvoidInit()

{

}

}


[/code]
是简单的消息模型,标题与正文属性:


[Serializable]

[code]publicclassPushMessageModel
{

publicintId{get;set;}

publicstringMSG_TITLE{get;set;}

publicstringMSG_CONTENT{get;set;}

}

[/code]


服务端推送具体类,记录日志,创建消息队列实例,监听,等待收取消息.这里我们使用的是AcitveMQ的.net客户端.ActiveMQListenAdapter是一个封装过的对象.


publicclassMQHubsConfig

[code]{
privatestaticILoggerlog=newLogger("MQHubsConfig");


///<summary>

///Registersthemqlistenandhubs.

///</summary>

publicstaticvoidRegisterMQListenAndHubs()

{

varactivemq=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>();

}

}

[/code]

上面有一句关键代码GlobalHost.ConnectionManager.GetHubContext<FeedHub>().Clients.All.receive(m);这里使用了GetHubContext方法后,直接来广播消息.

需要在MVCApplication下加载:


publicclassMvcApplication:System.Web.HttpApplication

[code]{
protectedvoidApplication_Start()

{

AreaRegistration.RegisterAllAreas();

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

RouteConfig.RegisterRoutes(RouteTable.Routes);

BundleConfig.RegisterBundles(BundleTable.Bundles);

MQHubsConfig.RegisterMQListenAndHubs();

}

}

[/code]

同时需要增加一个Starup.cs,用于Owin


[assembly:OwinStartup(typeof(RealTimeApp.Startup))]

[code]namespaceRealTimeApp
{

publicclassStartup

{

publicvoidConfiguration(IAppBuilderapp)

{

//Anyconnectionorhubwireupandconfigurationshouldgohere

app.MapSignalR();

}

}

}

[/code]
接下来是客户端App.js:


functionApp(){

[code]varinit=function(){
Feed();

$.connection.hub.logging=true;

$.connection.hub.start()

.done(function(){

console.log("Connected!");

$(document).trigger("Connected");

})

.fail(function(){console.log("CouldnotConnect!");});

};


init();

};

[/code]
Feed.js具体与SignalR.js通信,创建名为receive的function,与服务端对应


functionFeed(){

[code]varchat=undefined;

varinit=function(){


//Referencetheauto-generatedproxyforthehub.

chat=$.connection.feedHub;

//Createafunctionthatthehubcancallbacktodisplaymessages.

chat.client.receive=function(item){

varselector="ul.feed-listli[data-id="+item.Id+"]";

if(!($(selector).length>0)){

$("ul.feed-list").prepend($(".feed-template").render(item));

$("ul.feed-listli:gt(3)").remove();

}


$.messager.show({

title:'Tips',

msg:item.MSG_CONTENT,

showType:'show'

});



};


//Starttheconnection.

$.connection.hub.start().done(function(){

chat.server.init();

});


};


init();

};

[/code]

上面的javascript代码与服务端有通信,具体看如下图:





在Index.cshtml,我们需要引用SignalR客户端JS,放置hubs,这里我们使用了jsrender,easyui.js来呈现推送的消息.


@modeldynamic

[code]
@sectionScripts{

<linkhref="/Content/themes/default/window.css"rel="stylesheet"/>

<linkhref="~/Content/themes/default/progressbar.css"rel="stylesheet"/>

<linkhref="~/Content/themes/default/linkbutton.css"rel="stylesheet"/>

<scriptsrc="~/Scripts/jquery.signalR-2.1.2.min.js"></script>

<!--ReferencetheautogeneratedSignalRhubscript.-->

<scriptsrc="~/signalr/hubs"></script>


<scriptsrc="~/Scripts/jsrender.js"></script>

<scriptsrc="~/Scripts/jquery.easyui.min-1.4.1.js"></script>


@Scripts.Render("~/Scripts/project.js")


<scripttype="text/javascript">

$(document).ready(function(){

varapp=newApp();

});


</script>

}



<divclass="row-fluid">


<divclass="span8">

<divclass="widget">

<divclass="widget-header">

<h2>Feed</h2>

</div>

<divclass="widget-content">

<ulclass="span12feed-list"></ul>

</div>

</div>

</div>

</div>


<scriptclass="chat-template"type="text/x-jquery-tmpl">

<li>

<p>{{>Message}}</p>

</li>

</script>


<scriptclass="feed-template"type="text/x-jquery-tmpl">

<lidata-id="{{>Id}}">

<divclass="row-fluid">


<divclass="span8">

<h3>{{>MSG_CONTENT}}</h3>

</div>

</div>

</li>

</script>

[/code]
上代码服务端引用js的Script.Render,需要在BundleConfig.cs中加入以下代码:

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

同时我们构建一个WebAPI来发送需要推送的消息,片断代码:


///<summary>

[code]///SendMessage
///</summary>

///<paramname="messagemodel">Themessagemodel.</param>

///<returns></returns>

[HttpPost]

publicIHttpActionResultSendMessage(PushMessageModelmessagemodel)

{

returnSendToServer(messagemodel);


}


///<summary>

///Sendstoserver.

///</summary>

///<paramname="messagemodel">Themessagemodel.</param>

///<returns></returns>

privateIHttpActionResultSendToServer(PushMessageModelmessagemodel)

{


if(ModelState.IsValid)

{

if(messageRepository.SendMessage(messagemodel))

{

log.Debug("发送成功!");

returnOk();

}

else

{

log.ErrorFormat("发送失败!{0}",messagemodel);

returnContent(HttpStatusCode.ExpectationFailed,newException("sendmessageerror"));

}

}

else

{

log.ErrorFormat("参数验证失败!{0}",messagemodel);

returnContent(HttpStatusCode.BadRequest,ModelState);

}


}


[/code]
发送消息到ActiveMQ的关键代码:


publicclassMessageRepository:IMessageRepository

[code]{
privatestaticILoggerlog=newLogger("MessageRepository");


///<summary>

///发送消息

///</summary>

///<paramname="messagemodel"></param>

///<returns></returns>

publicboolSendMessage(PushMessageModelmessagemodel)

{

varactivemq=newActiveMQAdapter<PushMessageModel>(MQConfig.MQIpAddress,MQConfig.QueueDestination);

returnactivemq.SendMessage<PushMessageModel>(messagemodel)>0;

}

}

[/code]

如果您需要运行DEMO程序,需要构建基于ActiveMQ的消息队列,运行效果是这样的,我们在一个静态html中,发送一个ajax到webapi服务端,发送后





另一个website网站收到后,列表更新,并在右下角弹出框





IE的控制台输出:

HTML1300:Navigationoccurred.
File:Index
[11:05:25GMT+0800(ChinaStandardTime)]SignalR:Clientsubscribedtohub'feedhub'.
[11:05:25GMT+0800(ChinaStandardTime)]SignalR:Negotiatingwith'/signalr/negotiate?clientProtocol=1.4&connectionData=%5B%7B%22name%22%3A%22feedhub%22%7D%5D'.
[11:05:25GMT+0800(ChinaStandardTime)]SignalR:Thisbrowserdoesn'tsupportSSE.
[11:05:25GMT+0800(ChinaStandardTime)]SignalR:Bindingtoiframe'sloadevent.
[11:05:25GMT+0800(ChinaStandardTime)]SignalR:Iframetransportstarted.
[11:05:25GMT+0800(ChinaStandardTime)]SignalR:foreverFrametransportselected.Initiatingstartrequest.
[11:05:25GMT+0800(ChinaStandardTime)]SignalR:Thestartrequestsucceeded.Transitioningtotheconnectedstate.
[11:05:25GMT+0800(ChinaStandardTime)]SignalR:Nowmonitoringkeepalivewithawarningtimeoutof13333.333333333332andaconnectionlosttimeoutof20000.
[11:05:25GMT+0800(ChinaStandardTime)]SignalR:Invokingfeedhub.Init
Connected!
[11:05:25GMT+0800(ChinaStandardTime)]SignalR:Invokedfeedhub.Init
[11:07:12GMT+0800(ChinaStandardTime)]SignalR:Triggeringclienthubevent'receive'onhub'FeedHub'.
[11:07:18GMT+0800(ChinaStandardTime)]SignalR:Triggeringclienthubevent'receive'onhub'FeedHub'.
[11:07:32GMT+0800(ChinaStandardTime)]SignalR:Triggeringclienthubevent'receive'onhub'FeedHub'.
[11:07:51GMT+0800(ChinaStandardTime)]SignalR:Triggeringclienthubevent'receive'onhub'FeedHub'.
[11:09:25GMT+0800(ChinaStandardTime)]SignalR:Triggeringclienthubevent'receive'onhub'FeedHub'.

上面粗体是最后我们发的第5条信息控制台的输出.

好了,到这儿,由于篇幅有限,示例代码没有全部展示,可以在这儿下载,需要安装ActiveMQ
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐
章节导航