• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            franksunny的個(gè)人技術(shù)空間
            獲得人生中的成功需要的專注與堅(jiān)持不懈多過(guò)天才與機(jī)會(huì)。 ——C.W. Wendte

             

            關(guān)于RMsgQueue類的使用

             

            RMsgQueue類是Symbian OS EKA2才提供的一個(gè)類,最近因?yàn)轫?xiàng)目中要使用,為此對(duì)使用進(jìn)行如下小結(jié)。

            因?yàn)?/span>RMsgQueue類只是一個(gè)封裝好的內(nèi)核資源類,類似于RSocketRTimer類,要想使用它進(jìn)行異步操作就必須對(duì)其用AO類來(lái)封裝,從而來(lái)實(shí)現(xiàn)監(jiān)聽消息,在有消息過(guò)來(lái)時(shí)得到通知并根據(jù)消息內(nèi)容進(jìn)行相對(duì)應(yīng)的處理。

            那這個(gè)消息內(nèi)容又該如何定義呢?我們可以參看下RMsgQueue類定義

            template <typename T>

            class RMsgQueue : public RMsgQueueBase

            {

            public:

                   TInt CreateLocal(TInt aSize, TOwnerType aType=EOwnerProcess);

                   TInt CreateGlobal(const TDesC& aName, TInt aSize, TOwnerType aType=EOwnerProcess);

                   TInt Send(const T& aMsg);

                   void SendBlocking(const T& aMsg);

                   TInt Receive(T& aMsg);

                   void ReceiveBlocking(T& aMsg);

            };

            顯然該類RMsgQueue也是Symbian的廋模板類,具體消息內(nèi)容可以根據(jù)需求自定義類型,即如果傳遞的消息足夠簡(jiǎn)單則可以采用Tint類型來(lái)定義,考慮到我們的實(shí)際應(yīng)用對(duì)消息內(nèi)容進(jìn)行如下定義

            typedef enum _NetWork_Msg_Type

            {

                   NetworkSocketCreate,

                   NetworkSocketConnect,

                   NetworkSocketSend,

                   NetworkSocketRecv,

                   NetworkSocketClose,

            }NetWorkMsgType;

             

            typedef struct _NetWork_Msg

            {

                   NetWorkMsgType         m_msgType;

                   TInt32                         m_msgFd;

            }NetworkMsg;

            其中的NetworkMsg就是我們?cè)谶@里使用的消息內(nèi)容,其中的成員m_msgType NetWorkMsgType定義的枚舉值,表示消息類型,另一個(gè)成員m_msgFd是我們跨線程傳遞一個(gè)Id值。

            有了以上消息內(nèi)容,我們就可以簡(jiǎn)單的來(lái)定義消息隊(duì)列了

            RMsgQueue<NetworkMsg>  g_NetWorkMsgQue;

            如上已經(jīng)實(shí)例化了一個(gè)RMsgQueue對(duì)象,但是RMsgQueue對(duì)象必須要像RTimer一樣需要調(diào)用CreateLocal或者CreateGlobal才能創(chuàng)建起來(lái),那我們?cè)谀睦飫?chuàng)建它呢?這兩個(gè)創(chuàng)建又有什么區(qū)別呢?由于RMsgQueue可以是全局的也可以是局部的,假如使用局部的,那么類的封裝性較好,而且可以很好的跨進(jìn)程使用,但是缺點(diǎn)是需要傳遞對(duì)象,此時(shí)創(chuàng)建就可以使用CreateGlobal。考慮到我們只在一個(gè)進(jìn)程的不同線程間使用,同一進(jìn)程的線程間可以共享資源(內(nèi)存),所以這里我們就采用簡(jiǎn)單的全局變量來(lái)實(shí)現(xiàn)它,為此創(chuàng)建就用了簡(jiǎn)單的CreateLocal函數(shù),而且我們將其放在了AO的二階段構(gòu)造中,詳見示例代碼。

            至于AO的其它封裝,主要是利用RMsgQueue如下三個(gè)函數(shù)

            void RMsgQueue::NotifyDataAvailable(TRequestStatus& aStatus);

            TInt RMsgQueue::Send(const T& aMsg);

            TInt RMsgQueue::Receive(T& aMsg);

            先在封裝的AO中調(diào)用NotifyDataAvailable開啟消息的監(jiān)聽,然后就開始等待外部的Send函數(shù)調(diào)用發(fā)消息進(jìn)來(lái),一旦有消息Send進(jìn)來(lái)就進(jìn)入AORunl中,我們通過(guò)調(diào)用Receive函數(shù)來(lái)對(duì)傳遞進(jìn)來(lái)的消息內(nèi)容進(jìn)行解析和相應(yīng)處理。邏輯就這么簡(jiǎn)單,下面給出源代碼供參考。

            頭文件內(nèi)容:

            /*

             * MessageQueueAO.h

             *

             *  Created on: 2010-3-30

             *      Author: frank

             */

             

            #ifndef MESSAGEQUEUEAO_H_

            #define MESSAGEQUEUEAO_H_

             

            #include <e32base.h>

            #include <e32msgqueue.h>

             

            typedef enum _NetWork_Msg_Type

            {

                   NetworkConnect,

                   NetworkSocketCreate,

                   NetworkSocketConnect,

                   NetworkSocketSend,

                   NetworkSocketRecv,

                   NetworkSocketClose,

                   NetWorkDisConnect

            }NetWorkMsgType;

             

            typedef struct _NetWork_Msg

            {

                   NetWorkMsgType         m_msgType;

                   TInt32                         m_msgFd;

            }NetworkMsg;

             

            const TInt KNumberOfMsgs = 10;

            extern RMsgQueue<NetworkMsg>      g_NetWorkMsgQue;

             

            class CMessageQueueAO : public CActive

            {

            public:

                   // Cancel and destroy

                   virtual ~CMessageQueueAO();

                  

                   // Two-phased constructor.

                   static CMessageQueueAO* NewL();

             

                   // Two-phased constructor.

                   static CMessageQueueAO* NewLC();

            public:

                   // New functions

                   // Function for making the initial request

                   TInt StartMessageGet(const TDesC& aText=KNullDesC);

             

            private:

                   // C++ constructor

                   CMessageQueueAO();

             

                   // Second-phase constructor

                   void ConstructL();

                  

            private:

                   // From CActive

                   // Handle completion

                   void RunL();

             

                   // How to cancel me

                   void DoCancel();

             

                   // Override to handle leaves from RunL(). Default implementation causes

                   // the active scheduler to panic.

                   TInt RunError(TInt aError);

                  

            };

             

            #endif /* MESSAGEQUEUEAO_H_ */

            實(shí)現(xiàn)文件內(nèi)容

            /*

             * MessageQueueAO.cpp

             *

             *  Created on: 2010-3-30

             *      Author: frank

             */

             

            #include "MessageQueueAO.h"

             

            RMsgQueue<NetworkMsg>  g_NetWorkMsgQue;

             

            CMessageQueueAO::CMessageQueueAO()

            :CActive(EPriorityHigh)

                   {

                   // TODO Auto-generated constructor stub

                   }

             

            CMessageQueueAO::~CMessageQueueAO()

            {

                   // TODO Auto-generated destructor stub

                   Cancel();

            }

             

            CMessageQueueAO* CMessageQueueAO::NewL()

            {

                   CMessageQueueAO* self = CMessageQueueAO::NewLC();

                   CleanupStack::Pop(); // self;

                   return self;

            }

             

            CMessageQueueAO* CMessageQueueAO::NewLC()

            {

                   CMessageQueueAO* self = new (ELeave) CMessageQueueAO();

                   CleanupStack::PushL(self);

                   self->ConstructL();

                   return self;

            }

             

            void CMessageQueueAO::ConstructL()

            {

                   CActiveScheduler::Add(this); // Add to scheduler

                   g_NetWorkMsgQue.CreateLocal(KNumberOfMsgs);

            }

             

            TInt CMessageQueueAO::StartMessageGet(const TDesC& aText)

            {

                   g_NetWorkMsgQue.NotifyDataAvailable(iStatus);

                   SetActive(); // Tell scheduler a request is active

            }

             

            void SocketCreate(TInt32 aFd)

            {

            }

             

            void SocketRecv(TInt32 aFd)

            {

            }

             

            void SocketConnect(TInt32 aFd)

            {

            }

             

            void CMessageQueueAO::RunL()

            {

                if (iStatus.Int() == KErrNone)

                {

                       //接收數(shù)據(jù)

                       NetworkMsg msgfrmq;

                       g_NetWorkMsgQue.Receive(msgfrmq);

                       switch(msgfrmq.m_msgType)

                       {

                              case NetworkSocketCreate:

                                     LockMutexRaw(g_NetMgrMutex);

                                     SocketCreate(msgfrmq.m_msgFd);

                                     UnlockMutexRaw(g_NetMgrMutex);

                                     break;

                              case NetworkSocketConnect:

                                     LockMutexRaw(g_NetMgrMutex);

                                     SocketConnect(msgfrmq.m_msgFd);

                                     UnlockMutexRaw(g_NetMgrMutex);

                                     break;

                              case NetworkSocketRecv:

                                     LockMutexRaw(g_NetMgrMutex);

                                     SocketRecv(msgfrmq.m_msgFd);

                                     UnlockMutexRaw(g_NetMgrMutex);

                                     break;

                              case NetworkSocketClose:

                                     LockMutexRaw(g_NetMgrMutex);

                                     SocketClose(msgfrmq.m_msgFd);

                                     UnlockMutexRaw(g_NetMgrMutex);

                                     break;

                              default:

                                     break;

                       }

                       //Using ReceiveBlocking()

                       // msgqueue.ReceiveBlocking(msgfrmq);// 如果使用blocking 可能那邊要發(fā)送兩次消息這邊才會(huì)跑哦

                }

                g_NetWorkMsgQue.NotifyDataAvailable(iStatus);//開啟下一個(gè)消息的接收

                SetActive();

            }

             

            void CMessageQueueAO::DoCancel()

            {

                   if( IsActive() )

                   {

                          g_NetWorkMsgQue.CancelDataAvailable();

                   }

            }

             

            TInt CMessageQueueAO::RunError(TInt aError)

            {

                   return aError;

            }

            封裝完這個(gè)AO,大功就可以完成了,將這個(gè)AO放在一個(gè)獨(dú)立的線程中創(chuàng)建起來(lái),并調(diào)用StartMessageGet讓這個(gè)線程始終監(jiān)聽消息。外界線程通過(guò)調(diào)用g_NetWorkMsgQue.Send(msgfrmq)來(lái)給這個(gè)AO線程發(fā)消息并得到相應(yīng)的處理。在這里我就不過(guò)多展開了,因?yàn)橐婕皟蓚€(gè)線程間的操作,篇幅就太大了。

            在結(jié)束小結(jié)的時(shí)候,我想著如何實(shí)現(xiàn)IPC,這樣的話,這個(gè)小結(jié)就完整了,碰巧,在逛博客的時(shí)候,發(fā)現(xiàn)一篇博文總結(jié)得很好,而且言簡(jiǎn)意賅,為此轉(zhuǎn)載與下面,跟大家一起分享,博文原址http://blog.sina.com.cn/s/blog_63b4ee0d0100g3xc.html

             

            如何理解進(jìn)程間通信?

            先用一個(gè)通俗的例子來(lái)解釋:比如我們需要實(shí)現(xiàn)這樣一種模式,應(yīng)用由進(jìn)程A與進(jìn)程B兩部分組成,AUI,負(fù)責(zé)用戶交互;B沒(méi)有UI,完全后臺(tái)運(yùn)行,AB之間可以相互通信。就如彩信的模式,彩信到達(dá)后后臺(tái)下載,下載完給出提示信息(即用戶界面),閱讀彩信再激活信息程序。

            進(jìn)程通信即兩個(gè)并行進(jìn)程可以通過(guò)互相發(fā)送消息進(jìn)行合作,消息是通過(guò)消息緩沖而在進(jìn)程之間相互傳遞的。

            RMsgQueue3版提供的比較好的與事件機(jī)制融合的技術(shù), 2版只能使用其它傳統(tǒng)的, 信號(hào)量, 共享內(nèi)存等技術(shù).

            解決方案:

            讓我們來(lái)看代碼:

            Server

            void CP2PServer::ConstructL()

            {

                //創(chuàng)建

                iMsgQueue.CreateGlobal(KGLobalName, KNumberOfSlots, KMessageLength, EOwnerProcess);    

                CActiveScheduler::Add( this); // Add to scheduler

             

                iMsgQueue.NotifyDataAvailable( iStatus );//開始監(jiān)聽消息

                SetActive(); // Tell scheduler a request is active

                }

             

            void CP2PServer::RunL()

                {

                if (iStatus.Int() == KErrNone)

                    {

                    //接收數(shù)據(jù)

                    TRAPD(error,iMsgQueue.Receive( &str_SendData, KMessageLength));

                    if(error==KErrNone)

                        {

                        iObserver->HandleMessageReceiveL(str_SendData.DataBuf.Left(str_SendData.DataLength));

                        }

                    }

                }

             

            Client

            void CP2PClient::ConstructL()

                {

                //創(chuàng)建

                iMsgQueue.OpenGlobal(KGLobalName, EOwnerProcess);

                }

             

                //發(fā)送消息

            void CP2PClient::SendMessageL(const TDesC8& aSendMessage)

                {

                STR_SENDDATA temp;

                temp.DataLength = aSendMessage.Length();

                temp.DataBuf.Copy(aSendMessage);

                iMsgQueue.Send(&temp, KMessageLength);

                }

            就一些疑難問(wèn)題解決如下

            B線程創(chuàng)建一個(gè)“東東”,名字為KGLobalName,并且B線程開啟監(jiān)控消息 A線程在需要時(shí)使用帶KGLobalName參數(shù)的OpenGlobal函數(shù)打開同名, 然后發(fā)送消息出來(lái), 之后直接關(guān)閉B會(huì)收到此消息解析后開始進(jìn)行相應(yīng)的處理。

            上面的這個(gè)“東東”就是一個(gè)消息隊(duì)列, 只要?jiǎng)?chuàng)建者線程B存在, 就可以使用, 一般這個(gè)設(shè)計(jì)都是B始終運(yùn)行, 并且建立RMsgQueue, 其它進(jìn)程需要時(shí)打開, 發(fā)送消息,然后關(guān)閉 

            如果雙方都可以作為發(fā)送方與接受方,則每方都創(chuàng)建RMsgQueue,注意使用不同的名字。

             

             

            最后除了感謝上面這位牛人給出的總結(jié)外,我再補(bǔ)充一下,如果不是為了避免傳遞消息時(shí)的內(nèi)存拷貝操作,單向操作用C/S架構(gòu)更為可取,至于雙向操作,目前看來(lái)的確還是RMsgQueue好些,不知道大牛們覺(jué)得我這種猜想是否成立。

             

             

            posted on 2010-04-09 21:40 frank.sunny 閱讀(2026) 評(píng)論(1)  編輯 收藏 引用 所屬分類: symbian 開發(fā)

            FeedBack:
            # re: 關(guān)于RMsgQueue類的使用[未登錄](méi)
            2011-09-14 10:19 | zzg
            總結(jié)的不錯(cuò),學(xué)習(xí),轉(zhuǎn)走了  回復(fù)  更多評(píng)論
              

            常用鏈接

            留言簿(13)

            隨筆分類

            個(gè)人其它博客

            基礎(chǔ)知識(shí)鏈接

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久久网中文字幕| 久久国产三级无码一区二区| 亚洲级αV无码毛片久久精品| 久久久SS麻豆欧美国产日韩| 狠狠综合久久综合88亚洲| 996久久国产精品线观看| 伊人久久免费视频| 久久亚洲天堂| 亚洲va国产va天堂va久久| 免费精品99久久国产综合精品| 国产成人久久精品麻豆一区| 久久性精品| 精品永久久福利一区二区| 久久精品国产一区二区三区| 国产成人精品综合久久久| 久久久精品免费国产四虎| 色欲综合久久躁天天躁| 漂亮人妻被黑人久久精品| 国产免费久久精品99久久| 伊人久久大香线蕉亚洲五月天| 久久亚洲精品中文字幕三区| 怡红院日本一道日本久久| 久久精品国产亚洲αv忘忧草| 无码人妻久久一区二区三区| 99久久精品国产一区二区三区| 久久久久精品国产亚洲AV无码| 中文字幕亚洲综合久久2| 久久久久青草线蕉综合超碰| 国内精品伊人久久久久影院对白| 一本色道久久88精品综合| 99精品久久久久久久婷婷| 欧美丰满熟妇BBB久久久| 久久久精品日本一区二区三区 | 久久久久亚洲AV成人网人人软件 | 久久精品无码一区二区日韩AV| 久久精品无码专区免费东京热 | 波多野结衣久久精品| 国产无套内射久久久国产| 久久成人国产精品| 亚洲女久久久噜噜噜熟女| 人妻系列无码专区久久五月天|