久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

通過(guò)實(shí)例分析WCF Duplex消息交換...

 miky 2008-06-05

通過(guò)實(shí)例分析WCF Duplex消息交換

聊天室實(shí)例:點(diǎn)此下載 

    我在《Windows Communication Foundation之旅•三》中詳細(xì)介紹了WCF中的Duplex消息交換模式。因?yàn)镈uplex實(shí)現(xiàn)了客戶端與服務(wù)端雙向通信的功能,,故而我實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的聊天室程序,,展現(xiàn)Duplex的特點(diǎn)。有朋友在閱讀了這個(gè)例子之后,,提出一個(gè)問(wèn)題,,即“如何讓服務(wù)端向指定的客戶端發(fā)送消息?”很高興的是,,這位朋友在后來(lái)的郵件中說(shuō)到問(wèn)題已經(jīng)解決了,,思路是利用Singleton對(duì)象保存客戶端的Session。雖然存在一些比較奇怪的問(wèn)題,,然而總算是一種思路,。

    我的思路與之相似,需要服務(wù)端維護(hù)一個(gè)Dictionary的集合,,用以保存客戶端的信息,。服務(wù)端在發(fā)送消息時(shí),可以通過(guò)查找Dictionary對(duì)象,,識(shí)別符合條件的客戶端,。當(dāng)我還在思考這樣的方式能否解決問(wèn)題時(shí),我在WCF官方網(wǎng)站上偶然發(fā)現(xiàn)了一個(gè)同樣利用Duplex實(shí)現(xiàn)聊天室的Sample,。

    仔細(xì)閱讀了實(shí)例代碼,,我恍然發(fā)現(xiàn)自己在思考程序設(shè)計(jì)時(shí),并沒有理解WCF最核心的價(jià)值,,那就是“服務(wù)”,。作為實(shí)現(xiàn)SOA體系架構(gòu)的技術(shù)框架,WCF最重要的特征就在于能夠定義和提供服務(wù),。以聊天室程序?yàn)槔?,雖然服務(wù)端會(huì)參與消息的交互,但卻不應(yīng)該參與到聊天中,。也就是說(shuō),,客戶端與服務(wù)端的角色任務(wù)是不相同的。通過(guò)用例圖可以看到兩者之間的區(qū)別: 

chatroom01.gif
圖1  正確的用例圖            

chatroom02.gif
圖二  錯(cuò)誤的用例圖

    明確了以“服務(wù)”為核心的程序結(jié)構(gòu),,我們才能夠更好地利用WCF,,定制自己的服務(wù),分清楚服務(wù)的邊界,,定義好消息的格式,。雖然,,一個(gè)聊天室程序無(wú)法體現(xiàn)SOA的核心精神,然而樹立面向服務(wù)的思想確實(shí)必要的,。正如我們?cè)陂_始面向?qū)ο蟪绦蛟O(shè)計(jì)時(shí),,需要樹立面向?qū)ο蟮乃枷胍粯印?br>
    該聊天室程序的實(shí)現(xiàn)主要通過(guò)Duplex來(lái)實(shí)現(xiàn),其中又利用了MulticastDelegate與異步調(diào)用,。其中,,服務(wù)接口的定義如下:
    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IChatCallback))]
    interface IChat
    {
        [OperationContract(IsOneWay = false, IsInitiating = true, IsTerminating = false)]
        string[] Join(string name);

        [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
        void Say(string msg);

        [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
        void Whisper(string to, string msg);

        [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = true)]
        void Leave();
}

    回調(diào)接口的定義如下:
    interface IChatCallback
    {
        [OperationContract(IsOneWay = true)]
        void Receive(string senderName, string message);

        [OperationContract(IsOneWay = true)]
        void ReceiveWhisper(string senderName, string message);

        [OperationContract(IsOneWay = true)]
        void UserEnter(string name);

        [OperationContract(IsOneWay = true)]
        void UserLeave(string name);
    }

    服務(wù)提供了Join、Say,、Whisper與Leave等接口方法,,向?qū)?yīng)的是回調(diào)接口的接口方法。在實(shí)現(xiàn)IChat服務(wù)接口的服務(wù)類ChatService中,,定義了委托ChatEventHandler與ChatEventHandler類型的事件ChatEvent,,正是通過(guò)它實(shí)現(xiàn)了識(shí)別了客戶的消息廣播。方法如下:
     private void BroadcastMessage(ChatEventArgs e)
     {
         ChatEventHandler temp = ChatEvent;

         if (temp != null)
         {
             foreach (ChatEventHandler handler in temp.GetInvocationList())
             {
                handler.BeginInvoke(this, e, new AsyncCallback(EndAsync), null);
             }
         }
    }

    在客戶端加入聊天室程序之前,,該客戶端并沒有訂閱ChatEvent事件,,此時(shí)調(diào)用BroadcastMessage方法,,在通過(guò)GetInvocationList方法獲取MulticastDelegate時(shí),,不存在該客戶端的委托實(shí)例。因而,,其他客戶在通過(guò)聊天室進(jìn)行聊天時(shí),,不會(huì)將聊天信息發(fā)送到該客戶端。體現(xiàn)在程序中,,就是Join方法的如下代碼片斷:
    myEventHandler = new ChatEventHandler(MyEventHandler);
    ……

    callback = OperationContext.Current.GetCallbackChannel<IChatCallback>();
    ChatEventArgs e = new ChatEventArgs();
    e.msgType = MessageType.UserEnter;
    e.name = name;
    BroadcastMessage(e);
    ChatEvent += myEventHandler;
    ……

    注意看,,ChatEvent += myEventHandler語(yǔ)句是放在BroadcastMessage方法調(diào)用之后。一旦該客戶端加入聊天室程序之后,,再調(diào)用BroadcastMessage方法,,該客戶端就能接收消息了。

    ChatEvent事件指向的方法是MyEventHandler,,該方法將執(zhí)行回調(diào)接口的相關(guān)方法:
    private void MyEventHandler(object sender, ChatEventArgs e)
    {
        try
        {
            switch (e.msgType)
            {
                case MessageType.Receive:
                    callback.Receive(e.name, e.message);
                    break;
                case MessageType.ReceiveWhisper:
                    callback.ReceiveWhisper(e.name, e.message);
                    break;
                case MessageType.UserEnter:
                    callback.UserEnter(e.name);
                    break;
                case MessageType.UserLeave:
                    callback.UserLeave(e.name);
                    break;
            }
        }
        catch
        {
            Leave();
        }
    }

    還需要注意的是Whisper方法,。由于它實(shí)現(xiàn)了私聊功能,因而向指定客戶發(fā)送信息時(shí),,不應(yīng)該采用廣播方式,。如何找到指定客戶呢?這需要一個(gè)Dictionary集合,,保存客戶名和與之對(duì)應(yīng)的ChatEventHandler實(shí)例,。在執(zhí)行Whisper方法時(shí),就可以根據(jù)客戶名找到對(duì)應(yīng)的ChatEventHandler實(shí)例進(jìn)行調(diào)用:
    public void Whisper(string to, string msg)
    {
        ChatEventArgs e = new ChatEventArgs();
        e.msgType = MessageType.ReceiveWhisper;
        e.name = this.name;
        e.message = msg;
        try
        {
            ChatEventHandler chatterTo;
            lock (syncObj)
            {
                chatterTo = chatters[to];
            }
            chatterTo.BeginInvoke(this, e, new AsyncCallback(EndAsync), null);
        }
        catch (KeyNotFoundException)
        {
        }
    }

    在客戶端代碼中,,服務(wù)接口的調(diào)用采用了異步調(diào)用的方式,,例如客戶端加入聊天室:
    proxy = new ChatProxy(site);
    IAsyncResult iar = proxy.BeginJoin(myNick, new AsyncCallback(OnEndJoin), null);

    運(yùn)行聊天室程序時(shí),,服務(wù)端僅需要提供穩(wěn)定而持續(xù)的服務(wù)。聊天的參與者均為客戶端用戶,。因而服務(wù)端的運(yùn)行代碼如下所示:
    Uri uri = new Uri(ConfigurationManager.AppSettings["addr"]);
    ServiceHost host = new ServiceHost(typeof(NikeSoftChat.ChatService), uri);
    host.Open();
    Console.WriteLine("Chat service listen on endpoint {0}", uri.ToString());
    Console.WriteLine("Press ENTER to stop chat service...");
    Console.ReadLine();
    host.Abort();
    host.Close();

    本文Sample的作者是Nikola Paljetak,。鑒于作者本人在代碼所附的許可聲明,為了幫助大家閱讀本文,,在此附上Nikola Paljetak的Sample,,你可以在WCF官方網(wǎng)站中找到它。Nikola Paljetak的許可聲明如下:
    Permission is granted to anyone to use this software for any purpose, including commercial applications.

posted on 2007-03-08 11:50 張逸 閱讀(4040) 評(píng)論(11)  編輯 收藏 所屬分類: WCF & SOA

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多