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. JavaScript高级程序设计:第八章

    1.window对象——BOM的核心 BOM的核心对象时window,它表示浏览器的一个实例.在浏览器中,window对象有双重角色,它既是通过javascript访问浏览器窗口的一个接口,又是ECM ...

  2. Memcached缓存

    Memcached是"分布式"的内存对象缓存系统,那么不需要"分布"的.不需要共享的或者干脆规模小到只有一台服务器的应用,Memcached不会带来任何好处,相 ...

  3. Sharepoint 弹出消息提示框 .

    在event receiver中如何弹出一个类似winform中messagebox.show 的框? 那我要对用户显示一些错误信息或者提示信息怎么搞? 1. 如果是在ItemAdding或者其他进行 ...

  4. flash 右键菜单隐藏与修改

    来源:http://blog.sina.com.cn/s/blog_7264c84401014fmd.html import flash.ui.ContextMenu;import flash.ui. ...

  5. 初识Iaas,paas

    Iaas(Infrastructure-as-a-service),直译为基础设备作为一种服务. Paas(Platform as a service),直译为平台作为一种服务. 暂且忘掉这两个单词, ...

  6. PHP: 异常exception

    异常最常见于SDK调用中,函数执行失败时抛出异常,顺带错误码和错误信息. 先来看下PHP的异常处理相关函数: public Exception::__construct() ([ string $me ...

  7. js中冒泡事件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. MySQL慢日志查询全解析:从参数、配置到分析工具【转】

    转自: MySQL慢日志查询全解析:从参数.配置到分析工具 - MySQL - DBAplus社群——围绕数据库.大数据.PaaS云,运维圈最专注围绕“数据”的学习交流和专业社群http://dbap ...

  9. WPF之TabControl控件用法

    先创建实体基类:NotificationObject(用来被实体类继承) 实现属性更改通知接口: using System; using System.Collections.Generic; usi ...

  10. 虚拟机centos分区

    在计算机上安装 Linux 系统,对硬盘进行分区是一个非常重要的步骤,下面介绍几个分区方案. 方案 1 / :建议大小在 5GB 以上. swap :即交换分区,建议大小是物理内存的 1~2 倍. 方 ...