我心(xin)中的核心(xin)組件(可插(cha)拔(ba)的AOP)~第六回 消息(xi)組件~續
上一回寫消息組件已(yi)經是(shi)(shi)很(hen)久之前(qian)的(de)事了,這一(yi)次準備把消(xiao)(xiao)息(xi)組件后續(xu)的(de)東(dong)西說(shuo)一(yi)下(xia),事實(shi)上,第一(yi)篇文章主要講(jiang)的(de)是(shi)(shi)發(fa)消(xiao)(xiao)息(xi),而這一(yi)講(jiang)最要講(jiang)的(de)是(shi)(shi)收消(xiao)(xiao)息(xi),簡單的(de)說(shuo),就是(shi)(shi)消(xiao)(xiao)息(xi)到了服(fu)務器(qi)之后,如(ru)何從服(fu)務器(qi)實(shi)時(shi)的(de)發(fa)到指定客戶端,當然(ran),你可以使用JS的(de)輪(lun)詢,但由于種(zhong)種(zhong)原因,它并不被(bei)我(wo)推薦(jian),呵(he)呵(he).
準備知識:
NodeJS系列~第一個小例子,實現了request.querystring功能
干實事
當(dang)客戶端(duan)與(yu)服務(wu)器建立一個connection后,通過websocket技術,可以(yi)告訴服務(wu)器你的(de)(de)(de)(de)(de)(de)連(lian)接ID,這(zhe)時(shi),當(dang)然(ran)服務(wu)器檢查到有你的(de)(de)(de)(de)(de)(de)消息(xi)(xi)時(shi),直(zhi)接為你的(de)(de)(de)(de)(de)(de)connectionID去(qu)發請(qing)求,調你的(de)(de)(de)(de)(de)(de)客戶端(duan)方法,實現消息(xi)(xi)的(de)(de)(de)(de)(de)(de)顯示就(jiu)可以(yi)了(le),呵(he)呵(he).這(zhe)一切來(lai)的(de)(de)(de)(de)(de)(de)是(shi)那(nei)么容(rong)易(yi),事實上,它(ta)(ta)內容(rong)的(de)(de)(de)(de)(de)(de)技術遠不指這(zhe)些,如果我們自(zi)己開發websocket,那(nei)除(chu)非你是(shi)個協議(yi)高手(shou)(shou)+JS高手(shou)(shou),否(fou)則沒戲!所有,我們就(jiu)只好(hao)用人家寫好(hao)的(de)(de)(de)(de)(de)(de)東(dong)西了(le),而(er)微(wei)軟的(de)(de)(de)(de)(de)(de)SignalR就(jiu)是(shi)這(zhe)樣一個東(dong)西,當(dang)你的(de)(de)(de)(de)(de)(de)瀏(liu)覽(lan)器支持html5時(shi),它(ta)(ta)會(hui)與(yu)websocket方式進(jin)行與(yu)服務(wu)器端(duan)的(de)(de)(de)(de)(de)(de)通訊,不支持HTML5,它(ta)(ta)與(yu)會(hui)使用其它(ta)(ta)手(shou)(shou)段來(lai)實現這(zhe)個通訊的(de)(de)(de)(de)(de)(de)目的(de)(de)(de)(de)(de)(de).
下面我復制(zhi)之前寫過的signalR文章中(zhong)的部分代碼(ma):
第一(yi) 首(shou)先是服務器需要發(fa)布一(yi)個(ge)URI,來(lai)讓(rang)客(ke)戶端去訪問(wen)
[HubName("MessagePush ")] public class MessagePush : Hub { //實現消息推(tui)送(song)的邏輯 }
第二 一個(ge)集合,用來存儲正處于(yu)登陸的(de)(de)用戶,對(dui)于(yu)持久化的(de)(de)方式你可以(yi)使用內存,nosql等技術,這里沒有所謂,呵(he)呵(he),它(ta)是一個(ge)服(fu)務(wu)器端(duan)的(de)(de)方法,可以(yi)被客戶端(duan)JS去調(diao)用
static List<CurrentUser> ConnectedUsers = new List<CurrentUser>(); public void Connect(string url) { var id = Context.ConnectionId; var userID = (HttpContext.Current.Session == null ? "" : HttpContext.Current.Session["UserID"] ?? "").ToString(); if (ConnectedUsers.Count(x => x.ConnectionId == id) == 0) { ConnectedUsers.Add(new CurrentUser { ConnectionId = id, UserID = userID, }); Clients.Caller.onConnected(id, userID, url); Clients.Client(id).onNewUserConnected(id, userID); } }
第三 服(fu)務器調用客(ke)戶端的方法(fa)
Clients.AllExcept(id).onNewUserConnected(id, userID); //向所有客戶端推送,除了(le)自己之外 Clients.Client(id).onNewUserConnected(id, userID);//向自己去推(tui)送 Clients.All.onNewUserConnected(id, userID);//向所有客戶端推送
第四 客(ke)戶端代碼(ma),JS方法
<!--Reference the SignalR library. -->
<script src="/Scripts/jquery.signalR-1.0.0.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// Declare a proxy to reference the hub
var chatHub = $.connection.MessagePush;
registerClientMethods(chatHub);
// Start Hub
$.connection.hub.start().done(function () {
registerEvents(chatHub);
});
});
//注冊客戶端事件
function registerEvents(chatHub) {
$("#btn").click(function () {
chatHub.server.connect(url);
});
}
//注冊客戶端方法
function registerClientMethods(chatHub) {
chatHub.client.onNewUserConnected = function (id, userID) {
alert("新用戶完成為合法(fa)");
}
}
</script>
第五 測試//localhost:8080/MessagePush
第六 總結:事(shi)實(shi)上(shang),實(shi)現的過(guo)程很(hen)簡單,首(shou)先客戶(hu)端通(tong)過(guo)登(deng)(deng)陸(lu)告(gao)訴(su)服(fu)務器我(wo)來了(le),然(ran)后(hou)(hou)用(yong)戶(hu)向服(fu)務端發(fa)(fa)(fa)消(xiao)(xiao)息(xi)(xi),告(gao)訴(su)服(fu)務器我(wo)要給(gei)某某某發(fa)(fa)(fa)消(xiao)(xiao)息(xi)(xi)了(le),其次,服(fu)務器收到(dao)消(xiao)(xiao)息(xi)(xi)之后(hou)(hou),進行分發(fa)(fa)(fa)消(xiao)(xiao)息(xi)(xi),由于用(yong)戶(hu)登(deng)(deng)陸(lu)后(hou)(hou)已(yi)經在服(fu)務器上(shang)登(deng)(deng)記了(le),所以,很(hen)容易(yi)的找到(dao)了(le)"消(xiao)(xiao)息(xi)(xi)的接受者",最(zui)后(hou)(hou),服(fu)務端調用(yong)指定客戶(hu)端的JS方法(fa),去顯示和提(ti)醒用(yong)戶(hu):您老(lao)人家有新(xin)消(xiao)(xiao)息(xi)(xi)了(le),呵呵!