需求如下: 当配置文件发生改变时,广播配置信息给所有的进程,通知其重装配置. 

   1. WM_COPYDATA传递消息

   windows下最简单进程通信方式,利用WM_COPYDATA事件, 该事件能够传递一指针来携带消息. 

   

// 查找标题为Sample的窗口,向其发送一字符串
HWND hWnd = FindWindowW(NULL, "Sample");
if (hWnd != NULL)
{
this->setWindowTitle("dialog_send");

char szMsg[512];
strcpy(szMsg,"hello world");

COPYDATASTRUCT cpd;
cpd.dwData = 0;
cpd.cbData = strlen(szMsg);
cpd.lpData = szMsg;

// 同步发送消息
SendMessageW(hWnd, WM_COPYDATA, NULL, (LPARAM)&cpd);
}

 

同步发送消息,必须等待消息被处理完成才返回), 不能使用PostMessage(异步), 这样远远达不到实时要求. 测试了一下,发现大部分消息都只能采样同步方式发送, WM_CLEAR / WM_NOTIFYFORMAT / WM_USER / WM_DEVICECHANGE 等消息可以通过异步发送. 

  

   在不同进程之间传递一指针,各个进程其对应指针地址不同, 不可能取到相应字符串的值. 实际上WM_COPYDATA内部实现也用到共享内存, 那我们采用 windows消息通知 + 共享内存 来实现通知重装配置功能.

 

   2. windows 广播消息

/**
* windows 下提供了强大的广播消息函数,可以向网络驱动,应用程序,安装的驱动,系统级设备及组件发送消息
*/
DWORD bsm_app=BSM_APPLICATIONS; // 向所有应用程序发送消息
BroadcastSystemMessage(BSF_POSTMESSAGE,&bsm_app,WM_NOTIFYFORMAT,NULL,NULL);

 

   3. windows下共享内存

   服务端:

#include <windows.h>
#include <stdio.h>

#define MY_MEMORY_ID "kettas"

int main(int argc,char **argv)
{
/**
* 创建命名为kettas的共享内存
* dwMaximumSizeLow 映射对象低位最大尺寸设置为0时, xp下创建失败,这里设置为1024
*/
HANDLE lhShareMemory = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,1024,MY_MEMORY_ID);
if (lhShareMemory !=NULL)
{
printf("信息:共享数据打开失败");
return 1;
}

LPVOID buff;
buff = MapViewOfFile(lhShareMemory,FILE_MAP_WRITE,0,0,0); // 获取映射对象地址
// strcpy(strBuffer,"hello kettas"); // 写入数据

char *str="Hello world";
CopyMemory((PVOID)buff,str,strlen(str)); // 写入数据

UnmapViewOfFile((PVOID)buff);

getchar();
return 0;
}

   客户端:

#include <windows.h>
#include <stdio.h>

#define MY_MEMORY_ID "kettas"

int main(int argc,char **argv)
{
HANDLE handleFile;
handleFile= OpenFileMapping(FILE_MAP_ALL_ACCESS,false,MY_MEMORY_ID); //打开共享文件
if (handleFile==NULL)
{
printf("共享数据打开失败\n");
return 1;
}

char * str = NULL;
str=(char *) MapViewOfFile(handleFile,FILE_MAP_ALL_ACCESS,0,0,0); // 获取共享对象数据

printf("结果:%s",str);

UnmapViewOfFile(str);
CloseHandle(handleFile);

getchar();
return 0;
}

 

  当配置发生改变时, 服务端将数据写入共享内存,然后广播通知其它进程去共享内存中获取相应数据. 对于QT控制台程序,利用上往篇讲的, 新建一窗口后隐藏即可

/**
* @brief 获取广播消息
* @parm MRev 消息回调函数
*/
void GetNoticeMessage( MRev mRev )
{
if(mRev==NULL)
{
printf("错误:回调函数为空\n");
return;
}

// 全局指针赋值
GRevHandler=mRev;

#ifdef WIN32
hinstance = (HINSTANCE)GetModuleHandle(NULL);

if (!InitApplication(hinstance))
{
printf("错误:注册窗口失败\n");
return;
}

if (!InitInstance(hinstance, SW_HIDE)) // 隐藏窗口
{
printf("错误:新建窗口失败\n");
return;
}

#elif __unix
// 安装消息
InstallMessage();
#endif
}