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. enum ACCESSMODE
  11. {
  12. ReadMode = 0,
  13. WriteMode
  14. };
  15. // 定义消息回调函数
  16. typedef BOOL (CALLBACK *MsgQueueCallBack)(PVOID pData, DWORD dwSize);
  17. class CMsgQueue
  18. {
  19. public:
  20. CMsgQueue();
  21. CMsgQueue(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode);
  22. ~CMsgQueue();
  23. public:
  24. /**********************************************************************
  25. 函数名:Create
  26. 功能:  创建或打开消息队列
  27. 参数:
  28. [in]lpQueueName:    消息队列名称
  29. [in]dwSize:         每条消息的最大长度
  30. [in]accessMode      消息队列访问模式 ReadMode:只读  WriteMode:只写
  31. 返回值:
  32. 成功:TRUE  失败:FALSE
  33. **********************************************************************/
  34. BOOL Create(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode);
  35. /**********************************************************************
  36. 函数名:Read
  37. 功能:  从消息队列中读取一条消息
  38. 参数:
  39. [out]lpBuffer:            存放读取的数据
  40. [in] dwSize:              读取数据的大小
  41. [out]lpNumberOfBytesRead  实际读取数据的大小
  42. [in] dwTimeout            读取超时时间(ms) 0 立即返回  INFINITE 永远等待直至消息队列中有数据
  43. 返回值:
  44. 成功:TRUE  失败:FALSE
  45. ***********************************************************************/
  46. BOOL Read(LPVOID lpBuffer,DWORD dwSize,LPDWORD lpNumberOfBytesRead,DWORD dwTimeout = 0);
  47. /**********************************************************************
  48. 函数名:Write
  49. 功能:  向消息队列中写入一条消息
  50. 参数:
  51. [in]lpBuffer:      待写入的数据
  52. [in]dwSize:        写入数据的大小
  53. 返回值:
  54. 成功:TRUE  失败:FALSE
  55. **********************************************************************/
  56. BOOL Write(LPVOID lpBuffer,DWORD dwSize);
  57. // 设置消息回调函数
  58. BOOL SetMsgCallBack(MsgQueueCallBack pCallBackFun, PVOID pParam);
  59. // 关闭消息队列
  60. void Close(void);
  61. private:
  62. // 开启读取消息线程
  63. BOOL StartRevMsgThread(void);
  64. // 停止读取消息线程
  65. BOOL StopRevMsgThread(void);
  66. // 读取消息线程
  67. static void WINAPI RevMsgThread(LPVOID pParam);
  68. private:
  69. HANDLE m_hMsgQueue;
  70. DWORD m_dwQueueSize;
  71. MsgQueueCallBack m_MsgCallBack;
  72. HANDLE m_hRevMsgThread;
  73. BOOL m_bThreadExit;
  74. };
  75. #endif

/*******************************************************************
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)

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

#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类实现进程间通信:

  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. BOOL CALLBACK RecvMsgProc(PVOID pData, DWORD dwSize);
  13. // 创建只读消息队列
  14. CMsgQueue cMsgQueue(L"MsgQueueTest",1024,ReadMode);
  15. // 设置消息回调函数
  16. cMsgQueue.SetMsgCallBack(RecvMsgProc,NULL);
  17. // 处理消息
  18. BOOL CALLBACK RecvMsgProc(PVOID pData, DWORD dwSize)
  19. {
  20. printf("RecvMsgProc:Rev data Size=%d/n",dwSize);
  21. wchar_t data[256];
  22. memcpy(data, pData,dwSize);
  23. return TRUE;
  24. }
  25. //////////////////////////////////////////////////////////////////////////////////

WINCE下进程间通信(二)的更多相关文章

  1. WINCE下进程间通信(一)

    WINCE下进程间通信(一) 在WINCE开发中经常需要在不同的进程之间传递.共享数据,总结了一下,WINCE下进程间通信常用的方式有:Windows消息,共享内存,socket通信,管道,全局原子, ...

  2. Linux环境进程间通信(二):信号(下)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  3. Wince下sqlce数据库开发(二)

    上次写到使用数据绑定的方法测试本地sqlce数据库,这次使用访问SQL Server的方法访问sqlce,你会发现他们是如此的相似... 参考资料:http://www.cnblogs.com/rai ...

  4. 在Window Embedded CE(Wince)下使用OpenNETCF进行路由表的开发

    点击打开链接 背景 在开发3G项目的是时候,发现尽管3G网络连接已经建立成功了,但是数据不能发送成功,查明原因,由于路由表的问题,导致数据往ActiveSync连接的对端,也就是PC发送,而不是发送到 ...

  5. Linux环境进程间通信(二): 信号(上)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  6. WinCE下SQLCE数据库开发(VS,VB.net,VC++)

    WinCE下SQLCE数据库开发(VS,VB.net,VC++)   WinCE下SQLCE数据库开发 微软的SQL Server数据库由于其功能强大.方便使用,因此在很多行业都被广泛应用.基于智能设 ...

  7. WinCE下的串口通信开发(VS2005,VB.Net,VC++)

    WinCE下的串口通信开发(VS2005,VB.Net,VC++)   WinCE下的串口通信开发 一.利用Visual Basic 开发很简单,因为有现成的控件可以直接调用 以VS2005为例,首先 ...

  8. WinCE下读取注册表获得SD路径

    WinCE下读取注册表获得SD路径 [要点]WinCE注册表中[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SDMemory\] 下键Folde ...

  9. WinCE下GPRS自动拨号软件(GPRS AutoDial)

    之前在WinCE下调试USB的3G Modem时,写过一个拨号助手RASManager,基本能用.后来车机卖到俄罗斯去,客户老M提供了一个更好的GPRS自动拨号软件GPRS AutoDial,功能完善 ...

随机推荐

  1. HDU 5772 String problem

    最大权闭合子图.建图巧妙. 最大权闭合子图: #pragma comment(linker, "/STACK:1024000000,1024000000") #include< ...

  2. 《Windows驱动开发技术详解》之派遣函数

    驱动程序的主要功能是负责处理I/O请求,其中大部分I/O请求是在派遣函数中处理的.用户模式下所有对驱动程序的I/O请求,全部由操作系统转化为一个叫做IRP的数据结构,不同的IRP数据会被“派遣”到不同 ...

  3. java写文件时,输出不完整的原因以及解决方法close()或flush()

    在java的IO体系中,写文件通常会用到下面语句 BufferedWriter bw=new BufferedWriter(new FileWriter("sql语句.txt")) ...

  4. hdu_2147_kiki's game(博弈)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2147 题意:给你一个矩阵,从右上走到左下,每次只能向左或向下或向斜下走一格,先走到最后一格的会输,问k ...

  5. form异步无刷新提交,提交后可以显示弹出框,否则弹出框会被刷新不见,使用 preventDefault

    出错点:确认按钮上.加onclick事件.每次点击都会追加给form追加on监听方法.累加on方法,重复提交 suppress_exception:true 阻止异常 (百度推送 jdk) 向下按 p ...

  6. iPhone5s 等 64位真机 运行 带有百度地图等 仅支持32位系统API和SDK的问题

    将下图中画红色框的部分去掉,程序就不再支持64位了.iPhone5s 将使用它的32位兼容模式.(而不再是64位模式)百度地图也不会报错了.

  7. GsonFormat 报错

    GsonFormat原来也有bug 我是用GsonFormat来生成java bean的,但是运行起来居然报 Caused by: java.lang.NumberFormatException: E ...

  8. 以excel方式输出数据

    主类Test: public class D201 {//get set 方法略去 private String d201_01; private String d201_02; private St ...

  9. 文件描述符和exec() close_on_exec

    #include <fcntl.h> #include <iostream> #include <unistd.h> using namespace std; in ...

  10. asp之Eval()函数

    运行字符串: a=Eval("1+1") 结果为:a=2 运行函数: function aa(a) aa=a+1 end function b=Eval("aa(2)&q ...