适用共享内存与事件简单实现了一个多进程之间收发数据的代码, 发送数据后,所有接收线程都可以收到数据.
CEventMsgUtils.h
#pragma once
#include <windows.h>
#include <atlstr.h>
#define EVENT_MSG_DEFAULT_NAME "{AC921D0E-D1A8-4FB4-957E-3EBBF26980A3}"
class CEventMsgUtils
{
public:
CEventMsgUtils();
~CEventMsgUtils();
//创建
bool Create(CString strName = _T(EVENT_MSG_DEFAULT_NAME), bool m_isManualReset = true);
//打开
bool Open(CString strName = _T(EVENT_MSG_DEFAULT_NAME));
//关闭
void Close();
//获取信息
bool GetMsg(DWORD& dwCmd, CString& strMsg, DWORD dwTime = INFINITE) const;
//发送信息
bool SendMsg(const DWORD& dwCmd, const CString& strMsg);
//内存映射类
private:
class CFileMapping
{
public:
CFileMapping(void);
~CFileMapping(void);
bool Create(CString strName);
bool Open(CString strName);
void Close();
bool Read(DWORD& dwCmd, CString& strMsg) const;
bool Write(const DWORD& dwCmd, const CString& strMsg);
private:
HANDLE m_hMap;
LPTSTR m_hData;
HANDLE m_hMutex;
};
private:
HANDLE m_Hevent;
CFileMapping m_FileMap;
};
CEventMsgUtils.cpp
#include "CEventMsgUtils.h"
#include <strsafe.h>
#define EVENT_MSG_NAME "{86889D63-82FF-44F7-A7F6-1FD03B06F831}"
#define FILE_MAP_MUTEX_NAME "{ECF6AB92-E6DB-4E21-87B4-8218CC6D88E5}"
#define FILE_MAP_MAX_SIZE (1024 * 4)
CEventMsgUtils::CEventMsgUtils()
{
m_Hevent = NULL;
}
CEventMsgUtils::~CEventMsgUtils()
{
Close();
}
bool CEventMsgUtils::Create(CString strName, bool isManualReset)
{
if (NULL != m_Hevent)
{
return TRUE;
}
SECURITY_ATTRIBUTES sa = { 0 };
SECURITY_DESCRIPTOR sd = { 0 };
sa.nLength = sizeof(sa);
sa.bInheritHandle = FALSE;
sa.lpSecurityDescriptor = &sd;
//设置权限, 防止低权限进程不能打开
(void)::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
(void)::SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
if (!m_FileMap.Create(_T(EVENT_MSG_NAME)))
{
return false;
}
m_Hevent = ::CreateEvent(&sa, isManualReset, FALSE, strName);
if (m_Hevent)
{
return true;
}
return false;
}
bool CEventMsgUtils::Open(CString strName)
{
if (NULL != m_Hevent)
{
return TRUE;
}
if (!m_FileMap.Open(_T(EVENT_MSG_NAME)))
{
return false;
}
m_Hevent = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, strName);
if (m_Hevent)
{
return true;
}
return false;
}
void CEventMsgUtils::Close()
{
if (NULL != m_Hevent)
{
::CloseHandle(m_Hevent);
m_Hevent = NULL;
}
m_FileMap.Close();
}
bool CEventMsgUtils::GetMsg(DWORD& dwCmd, CString& strMsg, DWORD dwTime) const
{
bool isSuc = false;
DWORD dwWait = 0;
strMsg.Empty();
dwCmd = 0;
if (NULL == m_Hevent)
{
goto L_Clean;
}
dwWait = ::WaitForSingleObject(m_Hevent, dwTime);
if (WAIT_OBJECT_0 != dwWait)
{
goto L_Clean;
}
isSuc = m_FileMap.Read(dwCmd, strMsg);
if (!isSuc)
{
goto L_Clean;
}
isSuc = ::ResetEvent(m_Hevent);
L_Clean:
return isSuc;
}
bool CEventMsgUtils::SendMsg(const DWORD& dwCmd, const CString& strMsg)
{
bool isSuc = false;
if (NULL == m_Hevent)
{
return false;
}
isSuc = m_FileMap.Write(dwCmd, strMsg);
if (!isSuc)
{
goto L_Clean;
}
isSuc = ::SetEvent(m_Hevent);
L_Clean:
return isSuc;
}
CEventMsgUtils::CFileMapping::CFileMapping(void)
{
m_hMap = NULL;
m_hData = NULL;
m_hMutex = NULL;
}
CEventMsgUtils::CFileMapping::~CFileMapping(void)
{
Close();
}
bool CEventMsgUtils::CFileMapping::Create(CString strName)
{
SECURITY_ATTRIBUTES sa = { 0 };
SECURITY_DESCRIPTOR sd = { 0 };
BOOL bResult = FALSE;
sa.nLength = sizeof(sa);
sa.bInheritHandle = FALSE;
sa.lpSecurityDescriptor = &sd;
(void)::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
(void)::SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
m_hMutex = ::CreateMutex(&sa, FALSE, TEXT(FILE_MAP_MUTEX_NAME));
if (NULL == m_hMutex) {
goto L_Cleanup;
}
m_hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, FILE_MAP_MAX_SIZE, strName);
if (NULL == m_hMap) {
goto L_Cleanup;
}
m_hData = (LPTSTR)::MapViewOfFile(m_hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if (NULL == m_hData) {
goto L_Cleanup;
}
bResult = TRUE;
L_Cleanup:
if (!bResult) {
Close();
}
return bResult;
}
bool CEventMsgUtils::CFileMapping::Open(CString strName)
{
BOOL bResult = FALSE;
m_hMutex = ::OpenMutex(SYNCHRONIZE, FALSE, TEXT(FILE_MAP_MUTEX_NAME));
if (NULL == m_hMutex) {
goto L_Cleanup;
}
m_hMap = ::OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, strName);
if (NULL == m_hMap) {
goto L_Cleanup;
}
m_hData = (LPTSTR)::MapViewOfFile(m_hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if (NULL == m_hData) {
goto L_Cleanup;
}
bResult = TRUE;
L_Cleanup:
if (!bResult) {
Close();
}
return bResult;
}
void CEventMsgUtils::CFileMapping::Close()
{
if (m_hData) {
::UnmapViewOfFile(m_hData);
m_hData = NULL;
}
if (m_hMap) {
::CloseHandle(m_hMap);
m_hMap = NULL;
}
if (m_hMutex) {
::CloseHandle(m_hMutex);
m_hMutex = NULL;
}
}
bool CEventMsgUtils::CFileMapping::Read(DWORD& dwCmd, CString& strMsg) const
{
DWORD dwWait = 0;
LPDWORD lpData = (LPDWORD)m_hData;
if (!m_hMutex || !m_hData || !m_hMutex) {
return false;
}
dwWait = WaitForSingleObject(m_hMutex, INFINITE);
if (WAIT_OBJECT_0 != dwWait) {
return FALSE;
}
dwCmd = *((LPDWORD)lpData);
lpData++;
strMsg = (LPCTSTR)lpData;
ReleaseMutex(m_hMutex);
return true;;
}
bool CEventMsgUtils::CFileMapping::Write(const DWORD& dwCmd, const CString& strMsg)
{
HRESULT hr = S_OK;
DWORD dwWait = 0;
LPDWORD lpData = (LPDWORD)m_hData;
if (!m_hMutex || !m_hData || !m_hMutex) {
return false;
}
dwWait = WaitForSingleObject(m_hMutex, INFINITE);
if (WAIT_OBJECT_0 != dwWait) {
return false;
}
*lpData = dwCmd;
lpData++;
hr = StringCchCopy((LPTSTR)lpData, FILE_MAP_MAX_SIZE / sizeof(TCHAR), strMsg.GetString());
ReleaseMutex(m_hMutex);
return S_OK == hr;
}
测试代码:
main.cpp
// CEventUtils.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <thread>
#include <mutex>
#include "CEventMsgUtils.h"
int main()
{
setlocale(LC_ALL, "");
CEventMsgUtils obj;
obj.Create();
for (int i = 0; i < 20; i++)
{
std::thread([]() {
CEventMsgUtils obj;
obj.Open();
CString msg;
DWORD dwCmd = 0;
static std::mutex Mutex;
while (true)
{
if (obj.GetMsg(dwCmd, msg))
{
std::lock_guard<std::mutex> lock(Mutex);
std::wcout << _T("tid: ") << std::this_thread::get_id() << _T(" cmd: ") << std::this_thread::get_id() << dwCmd << _T(" msg: ") << msg.GetString() << std::endl;
}
else
{
std::lock_guard<std::mutex> lock(Mutex);
std::wcout << _T("error!!!") << std::endl;
break;
}
if (0 == msg.CompareNoCase(_T("Quit")))
{
std::lock_guard<std::mutex> lock(Mutex);
std::wcout << _T("tid: ") << std::this_thread::get_id() << _T(" cmd: ") << std::this_thread::get_id() << dwCmd << _T(" msg: ") << msg.GetString() << std::endl;
break;
}
}
obj.Close();
}).detach();
}
int i = 0;
TCHAR szBuf[MAX_PATH] = { 0 };
DWORD dwCmd = 0;
while (true)
{
std::wcout << _T("Input: ");
std::wcin >> szBuf;
dwCmd = _tstoi(szBuf);
std::wcin >> szBuf;
i++;
obj.SendMsg(dwCmd, szBuf);
if (CString(_T("Quit")) == szBuf)
{
//break;
}
Sleep(500);
}
obj.Close();
return 0;
}