WINCE下進程間通信(二)

接着前面的文章《WINCE下進程間通信(一)》,現在介紹進程間通信的另一種方法。

 三、管道(消息隊列)

       WINCE並不支持類似於PC機上匿名管道、命名管道的通信方式,但CE下提供了一種點對點消息隊列的方法,其工作原理與管道非常類似:在通信的兩端分別建立一個讀隊列和寫隊列,寫進程往消息隊列一端寫入數據,讀進程從消息隊列另一端讀取數據。

       消息隊列相關的系統API主要有:CreateMsgQueue()、ReadMsgQueue()、WriteMsgQuue()和CloseMsgQueue()。爲了方便消息隊列的操作,封裝了一個消息隊列操作類,參考代碼如下:

       頭文件(CMsgQueue.h)

  1. /******************************************************************* 
  2.  filename: CMsgQueue.h 
  3.  purpose:   封裝了WINCE下消息隊列操作類 
  4.  author:    firehood 
  5.  created:   2011.03.23 
  6. ********************************************************************/  
  7. #ifndef _MSG_QUEUE_H  
  8. #define _MSG_QUEUE_H  
  9.   
  10. // 消息隊列訪問模式  
  11. enum ACCESSMODE  
  12. {  
  13.     ReadMode = 0,  
  14.     WriteMode  
  15. };  
  16.   
  17. // 定義消息回調函數  
  18. typedef BOOL (CALLBACK *MsgQueueCallBack)(PVOID pData, DWORD dwSize);  
  19.   
  20. class CMsgQueue  
  21. {  
  22. public:  
  23.     CMsgQueue();  
  24.     CMsgQueue(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode);  
  25.     ~CMsgQueue();  
  26. public:  
  27.     /********************************************************************** 
  28.     函數名:Create 
  29.     功能:  創建或打開消息隊列   
  30.     參數: 
  31.             [in]lpQueueName:    消息隊列名稱 
  32.             [in]dwSize:         每條消息的最大長度 
  33.             [in]accessMode      消息隊列訪問模式 ReadMode:只讀  WriteMode:只寫 
  34.     返回值: 
  35.             成功:TRUE  失敗:FALSE 
  36.     **********************************************************************/  
  37.     BOOL Create(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode);  
  38.   
  39.     /********************************************************************** 
  40.     函數名:Read 
  41.     功能:  從消息隊列中讀取一條消息 
  42.     參數: 
  43.             [out]lpBuffer:            存放讀取的數據 
  44.             [in] dwSize:              讀取數據的大小 
  45.             [out]lpNumberOfBytesRead  實際讀取數據的大小 
  46.             [in] dwTimeout            讀取超時時間(ms) 0 立即返回  INFINITE 永遠等待直至消息隊列中有數據 
  47.     返回值: 
  48.             成功:TRUE  失敗:FALSE 
  49.     ***********************************************************************/  
  50.     BOOL Read(LPVOID lpBuffer,DWORD dwSize,LPDWORD lpNumberOfBytesRead,DWORD dwTimeout = 0);  
  51.   
  52.     /********************************************************************** 
  53.     函數名:Write 
  54.     功能:  向消息隊列中寫入一條消息    
  55.     參數: 
  56.             [in]lpBuffer:      待寫入的數據 
  57.             [in]dwSize:        寫入數據的大小 
  58.     返回值: 
  59.             成功:TRUE  失敗:FALSE 
  60.     **********************************************************************/  
  61.     BOOL Write(LPVOID lpBuffer,DWORD dwSize);  
  62.   
  63.     // 設置消息回調函數  
  64.     BOOL SetMsgCallBack(MsgQueueCallBack pCallBackFun, PVOID pParam);  
  65.     // 關閉消息隊列  
  66.     void Close(void);  
  67. private:  
  68.     // 開啓讀取消息線程  
  69.     BOOL StartRevMsgThread(void);  
  70.     // 停止讀取消息線程  
  71.     BOOL StopRevMsgThread(void);  
  72.     // 讀取消息線程  
  73.     static void WINAPI RevMsgThread(LPVOID pParam);  
  74. private:  
  75.     HANDLE m_hMsgQueue;  
  76.     DWORD m_dwQueueSize;  
  77.     MsgQueueCallBack m_MsgCallBack;  
  78.     HANDLE m_hRevMsgThread;  
  79.     BOOL m_bThreadExit;  
  80. };  
  81. #endif  

 源文件(CMsgQueue.cpp)

  1. #include "stdafx.h"  
  2. #include "CMsgQueue.h"  
  3.   
  4. CMsgQueue::CMsgQueue()  
  5. {  
  6.     m_hMsgQueue = NULL;  
  7.     m_dwQueueSize = 0;  
  8.     m_hRevMsgThread = NULL;  
  9.     m_bThreadExit = FALSE;  
  10.     m_MsgCallBack = NULL;  
  11. }  
  12.   
  13. CMsgQueue::CMsgQueue(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode)  
  14. {  
  15.     Create(lpQueueName,dwSize,accessMode);  
  16. }  
  17.   
  18. CMsgQueue::~CMsgQueue()  
  19. {  
  20.     Close();  
  21. }  
  22.   
  23. BOOL CMsgQueue::Create(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode)  
  24. {  
  25.     if(!m_hMsgQueue)  
  26.     {  
  27.         m_hRevMsgThread = NULL;  
  28.         m_bThreadExit = FALSE;  
  29.         m_MsgCallBack = NULL;  
  30.         m_dwQueueSize = dwSize;  
  31.         // 創建消息隊列  
  32.         MSGQUEUEOPTIONS options;  
  33.         options.dwSize = sizeof(options);  
  34.         options.dwFlags = MSGQUEUE_NOPRECOMMIT|MSGQUEUE_ALLOW_BROKEN;  
  35.         options.dwMaxMessages = 0;  
  36.         options.cbMaxMessage = dwSize;  
  37.         options.bReadAccess = (accessMode==ReadMode) ? TRUE : FALSE;  
  38.         m_hMsgQueue =::CreateMsgQueue(lpQueueName,&options);  
  39.     }  
  40.     return TRUE;  
  41. }  
  42.   
  43. void CMsgQueue::Close(void)  
  44. {  
  45.     if(m_hMsgQueue)  
  46.     {  
  47.         ::CloseMsgQueue(m_hMsgQueue);  
  48.         m_hMsgQueue = NULL;  
  49.     }  
  50.     // 註銷回調函數  
  51.     SetMsgCallBack(NULL,NULL);  
  52. }  
  53.   
  54. BOOL CMsgQueue::Read(LPVOID lpBuffer,DWORD dwSize,LPDWORD lpNumberOfBytesRead,DWORD dwTimeout)  
  55. {  
  56.     if(m_hMsgQueue == NULL || lpBuffer == NULL)  
  57.     {  
  58.         return FALSE;  
  59.     }  
  60.     DWORD dwFlag = 0;  
  61.     // 從消息隊列頭部讀出數據   
  62.     if(!::ReadMsgQueue(m_hMsgQueue,lpBuffer,dwSize,lpNumberOfBytesRead,dwTimeout,&dwFlag))  
  63.     {  
  64.         return FALSE;  
  65.     }  
  66.     return TRUE;  
  67. }  
  68. BOOL CMsgQueue::Write(LPVOID lpBuffer,DWORD dwSize)  
  69. {  
  70.     if(m_hMsgQueue == NULL || lpBuffer == NULL)  
  71.     {  
  72.         return FALSE;  
  73.     }  
  74.     // 向消息隊列尾部寫入數據  
  75.     if(!::WriteMsgQueue(m_hMsgQueue,lpBuffer,dwSize,0,0))  
  76.     {  
  77.         return FALSE;  
  78.     }  
  79.     return TRUE;  
  80. }  
  81.   
  82. BOOL CMsgQueue::SetMsgCallBack(MsgQueueCallBack pCallBackFun, PVOID pParam)  
  83. {  
  84.     m_MsgCallBack = pCallBackFun;  
  85.     if (m_MsgCallBack)  
  86.     {  
  87.         if (m_hRevMsgThread == NULL)  
  88.         {  
  89.             // 開啓讀取線程  
  90.             return StartRevMsgThread();  
  91.         }  
  92.     }  
  93.     else  
  94.     {  
  95.         if (m_hRevMsgThread)  
  96.         {  
  97.             // 關閉讀取線程  
  98.             return StopRevMsgThread();  
  99.         }  
  100.     }  
  101.     return TRUE;  
  102. }  
  103.   
  104. BOOL CMsgQueue::StartRevMsgThread(void)  
  105. {  
  106.     if(m_hRevMsgThread == NULL)  
  107.     {  
  108.         // 創建讀取消息線程  
  109.         m_hRevMsgThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CMsgQueue::RevMsgThread, this, 0, NULL);  
  110.     }  
  111.     return (m_hRevMsgThread ? TRUE : FALSE);  
  112. }  
  113.   
  114. BOOL CMsgQueue::StopRevMsgThread(void)  
  115. {  
  116.     if(m_hRevMsgThread)  
  117.     {  
  118.         m_bThreadExit = TRUE;  
  119.         // 等待線程成功退出  
  120.         WaitForSingleObject(m_hRevMsgThread,INFINITE);  
  121.         CloseHandle(m_hRevMsgThread);  
  122.         m_hRevMsgThread = NULL;  
  123.         m_hRevMsgThread = FALSE;  
  124.     }  
  125.     return ((m_hRevMsgThread==NULL) ? TRUE : FALSE);  
  126. }  
  127.   
  128. void WINAPI CMsgQueue::RevMsgThread(LPVOID pParam)  
  129. {  
  130.      CMsgQueue *pMsgQueue=(CMsgQueue*)pParam;  
  131.      LPVOID lpBuffer;  
  132.      DWORD dwReadNums=0;  
  133.      lpBuffer=(LPVOID)malloc(pMsgQueue->m_dwQueueSize);  
  134.      while(!pMsgQueue->m_bThreadExit)  
  135.      {  
  136.          if(!pMsgQueue->m_hMsgQueue )  
  137.              break;  
  138.          // 從消息隊列中讀取一條消息(阻塞模式)  
  139.          BOOL ret=pMsgQueue->Read(lpBuffer,pMsgQueue->m_dwQueueSize,&dwReadNums,INFINITE);  
  140.          printf("Read ret=%d,dwReadNums=%d/n",ret,dwReadNums);  
  141.          if(dwReadNums>0)  
  142.          {  
  143.              // 調用回調函數  
  144.              if(pMsgQueue->m_MsgCallBack)  
  145.                  pMsgQueue->m_MsgCallBack(lpBuffer,dwReadNums);  
  146.          }  
  147.      }  
  148.      printf("RevMsgThread exit.../n");  
  149.      free(lpBuffer);  
  150. }  

 使用CMsgQueue類實現進程間通信:

  1. // 發送進程  
  2. //////////////////////////////////////////////////////////////////////////////////  
  3. // 創建只寫消息隊列  
  4. CMsgQueue cMsgQueue(L"MsgQueueTest",1024,WriteMode);  
  5. // 往消息隊列寫數據  
  6. cMsgQueue.Write(L"Hello Word!",22);  
  7. cMsgQueue.Close();  
  8. //////////////////////////////////////////////////////////////////////////////////  
  9.   
  10. // 接收進程  
  11. //////////////////////////////////////////////////////////////////////////////////  
  12. // 聲明消息回調函數  
  13. BOOL CALLBACK RecvMsgProc(PVOID pData, DWORD dwSize);  
  14.   
  15. // 創建只讀消息隊列  
  16. CMsgQueue cMsgQueue(L"MsgQueueTest",1024,ReadMode);  
  17. // 設置消息回調函數  
  18. cMsgQueue.SetMsgCallBack(RecvMsgProc,NULL);  
  19.   
  20. // 處理消息  
  21. BOOL CALLBACK RecvMsgProc(PVOID pData, DWORD dwSize)  
  22. {  
  23.     printf("RecvMsgProc:Rev data Size=%d/n",dwSize);  
  24.     wchar_t data[256];  
  25.     memcpy(data, pData,dwSize);  
  26.     return TRUE;  
  27. }  
  28. //////////////////////////////////////////////////////////////////////////////////  

發佈了82 篇原創文章 · 獲贊 22 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章