多进程通信, 带消息的事件(Win32, C++)

47 篇文章 0 订阅

适用共享内存与事件简单实现了一个多进程之间收发数据的代码, 发送数据后,所有接收线程都可以收到数据.

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;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值