接着前面的文章《WINCE下進程間通信(一)》,現在介紹進程間通信的另一種方法。
三、管道(消息隊列)
WINCE並不支持類似於PC機上匿名管道、命名管道的通信方式,但CE下提供了一種點對點消息隊列的方法,其工作原理與管道非常類似:在通信的兩端分別建立一個讀隊列和寫隊列,寫進程往消息隊列一端寫入數據,讀進程從消息隊列另一端讀取數據。
消息隊列相關的系統API主要有:CreateMsgQueue()、ReadMsgQueue()、WriteMsgQuue()和CloseMsgQueue()。爲了方便消息隊列的操作,封裝了一個消息隊列操作類,參考代碼如下:
頭文件(CMsgQueue.h)
- /*******************************************************************
- filename: CMsgQueue.h
- purpose: 封裝了WINCE下消息隊列操作類
- author: firehood
- created: 2011.03.23
- ********************************************************************/
- #ifndef _MSG_QUEUE_H
- #define _MSG_QUEUE_H
- // 消息隊列訪問模式
- enum ACCESSMODE
- {
- ReadMode = 0,
- WriteMode
- };
- // 定義消息回調函數
- typedef BOOL (CALLBACK *MsgQueueCallBack)(PVOID pData, DWORD dwSize);
- class CMsgQueue
- {
- public:
- CMsgQueue();
- CMsgQueue(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode);
- ~CMsgQueue();
- public:
- /**********************************************************************
- 函數名:Create
- 功能: 創建或打開消息隊列
- 參數:
- [in]lpQueueName: 消息隊列名稱
- [in]dwSize: 每條消息的最大長度
- [in]accessMode 消息隊列訪問模式 ReadMode:只讀 WriteMode:只寫
- 返回值:
- 成功:TRUE 失敗:FALSE
- **********************************************************************/
- BOOL Create(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode);
- /**********************************************************************
- 函數名:Read
- 功能: 從消息隊列中讀取一條消息
- 參數:
- [out]lpBuffer: 存放讀取的數據
- [in] dwSize: 讀取數據的大小
- [out]lpNumberOfBytesRead 實際讀取數據的大小
- [in] dwTimeout 讀取超時時間(ms) 0 立即返回 INFINITE 永遠等待直至消息隊列中有數據
- 返回值:
- 成功:TRUE 失敗:FALSE
- ***********************************************************************/
- BOOL Read(LPVOID lpBuffer,DWORD dwSize,LPDWORD lpNumberOfBytesRead,DWORD dwTimeout = 0);
- /**********************************************************************
- 函數名:Write
- 功能: 向消息隊列中寫入一條消息
- 參數:
- [in]lpBuffer: 待寫入的數據
- [in]dwSize: 寫入數據的大小
- 返回值:
- 成功:TRUE 失敗:FALSE
- **********************************************************************/
- BOOL Write(LPVOID lpBuffer,DWORD dwSize);
- // 設置消息回調函數
- BOOL SetMsgCallBack(MsgQueueCallBack pCallBackFun, PVOID pParam);
- // 關閉消息隊列
- void Close(void);
- private:
- // 開啓讀取消息線程
- BOOL StartRevMsgThread(void);
- // 停止讀取消息線程
- BOOL StopRevMsgThread(void);
- // 讀取消息線程
- static void WINAPI RevMsgThread(LPVOID pParam);
- private:
- HANDLE m_hMsgQueue;
- DWORD m_dwQueueSize;
- MsgQueueCallBack m_MsgCallBack;
- HANDLE m_hRevMsgThread;
- BOOL m_bThreadExit;
- };
- #endif
源文件(CMsgQueue.cpp)
- #include "stdafx.h"
- #include "CMsgQueue.h"
- CMsgQueue::CMsgQueue()
- {
- m_hMsgQueue = NULL;
- m_dwQueueSize = 0;
- m_hRevMsgThread = NULL;
- m_bThreadExit = FALSE;
- m_MsgCallBack = NULL;
- }
- CMsgQueue::CMsgQueue(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode)
- {
- Create(lpQueueName,dwSize,accessMode);
- }
- CMsgQueue::~CMsgQueue()
- {
- Close();
- }
- BOOL CMsgQueue::Create(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode)
- {
- if(!m_hMsgQueue)
- {
- m_hRevMsgThread = NULL;
- m_bThreadExit = FALSE;
- m_MsgCallBack = NULL;
- m_dwQueueSize = dwSize;
- // 創建消息隊列
- MSGQUEUEOPTIONS options;
- options.dwSize = sizeof(options);
- options.dwFlags = MSGQUEUE_NOPRECOMMIT|MSGQUEUE_ALLOW_BROKEN;
- options.dwMaxMessages = 0;
- options.cbMaxMessage = dwSize;
- options.bReadAccess = (accessMode==ReadMode) ? TRUE : FALSE;
- m_hMsgQueue =::CreateMsgQueue(lpQueueName,&options);
- }
- return TRUE;
- }
- void CMsgQueue::Close(void)
- {
- if(m_hMsgQueue)
- {
- ::CloseMsgQueue(m_hMsgQueue);
- m_hMsgQueue = NULL;
- }
- // 註銷回調函數
- SetMsgCallBack(NULL,NULL);
- }
- BOOL CMsgQueue::Read(LPVOID lpBuffer,DWORD dwSize,LPDWORD lpNumberOfBytesRead,DWORD dwTimeout)
- {
- if(m_hMsgQueue == NULL || lpBuffer == NULL)
- {
- return FALSE;
- }
- DWORD dwFlag = 0;
- // 從消息隊列頭部讀出數據
- if(!::ReadMsgQueue(m_hMsgQueue,lpBuffer,dwSize,lpNumberOfBytesRead,dwTimeout,&dwFlag))
- {
- return FALSE;
- }
- return TRUE;
- }
- BOOL CMsgQueue::Write(LPVOID lpBuffer,DWORD dwSize)
- {
- if(m_hMsgQueue == NULL || lpBuffer == NULL)
- {
- return FALSE;
- }
- // 向消息隊列尾部寫入數據
- if(!::WriteMsgQueue(m_hMsgQueue,lpBuffer,dwSize,0,0))
- {
- return FALSE;
- }
- return TRUE;
- }
- BOOL CMsgQueue::SetMsgCallBack(MsgQueueCallBack pCallBackFun, PVOID pParam)
- {
- m_MsgCallBack = pCallBackFun;
- if (m_MsgCallBack)
- {
- if (m_hRevMsgThread == NULL)
- {
- // 開啓讀取線程
- return StartRevMsgThread();
- }
- }
- else
- {
- if (m_hRevMsgThread)
- {
- // 關閉讀取線程
- return StopRevMsgThread();
- }
- }
- return TRUE;
- }
- BOOL CMsgQueue::StartRevMsgThread(void)
- {
- if(m_hRevMsgThread == NULL)
- {
- // 創建讀取消息線程
- m_hRevMsgThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CMsgQueue::RevMsgThread, this, 0, NULL);
- }
- return (m_hRevMsgThread ? TRUE : FALSE);
- }
- BOOL CMsgQueue::StopRevMsgThread(void)
- {
- if(m_hRevMsgThread)
- {
- m_bThreadExit = TRUE;
- // 等待線程成功退出
- WaitForSingleObject(m_hRevMsgThread,INFINITE);
- CloseHandle(m_hRevMsgThread);
- m_hRevMsgThread = NULL;
- m_hRevMsgThread = FALSE;
- }
- return ((m_hRevMsgThread==NULL) ? TRUE : FALSE);
- }
- void WINAPI CMsgQueue::RevMsgThread(LPVOID pParam)
- {
- CMsgQueue *pMsgQueue=(CMsgQueue*)pParam;
- LPVOID lpBuffer;
- DWORD dwReadNums=0;
- lpBuffer=(LPVOID)malloc(pMsgQueue->m_dwQueueSize);
- while(!pMsgQueue->m_bThreadExit)
- {
- if(!pMsgQueue->m_hMsgQueue )
- break;
- // 從消息隊列中讀取一條消息(阻塞模式)
- BOOL ret=pMsgQueue->Read(lpBuffer,pMsgQueue->m_dwQueueSize,&dwReadNums,INFINITE);
- printf("Read ret=%d,dwReadNums=%d/n",ret,dwReadNums);
- if(dwReadNums>0)
- {
- // 調用回調函數
- if(pMsgQueue->m_MsgCallBack)
- pMsgQueue->m_MsgCallBack(lpBuffer,dwReadNums);
- }
- }
- printf("RevMsgThread exit.../n");
- free(lpBuffer);
- }
使用CMsgQueue類實現進程間通信:
- // 發送進程
- //////////////////////////////////////////////////////////////////////////////////
- // 創建只寫消息隊列
- CMsgQueue cMsgQueue(L"MsgQueueTest",1024,WriteMode);
- // 往消息隊列寫數據
- cMsgQueue.Write(L"Hello Word!",22);
- cMsgQueue.Close();
- //////////////////////////////////////////////////////////////////////////////////
- // 接收進程
- //////////////////////////////////////////////////////////////////////////////////
- // 聲明消息回調函數
- BOOL CALLBACK RecvMsgProc(PVOID pData, DWORD dwSize);
- // 創建只讀消息隊列
- CMsgQueue cMsgQueue(L"MsgQueueTest",1024,ReadMode);
- // 設置消息回調函數
- cMsgQueue.SetMsgCallBack(RecvMsgProc,NULL);
- // 處理消息
- BOOL CALLBACK RecvMsgProc(PVOID pData, DWORD dwSize)
- {
- printf("RecvMsgProc:Rev data Size=%d/n",dwSize);
- wchar_t data[256];
- memcpy(data, pData,dwSize);
- return TRUE;
- }
- //////////////////////////////////////////////////////////////////////////////////