Windows进程通信--共享内存(二)

一、问题:

上篇文章留下了一些问题,这次主要解决以下两个问题:

1.往共享内存写数据时,并不确认共享内存里面的数据是否已经被处理过了

2.发送数据大小大于共享内存大小时,会存在数据丢失问题

 

二、实现方式:

1.增加一个读事件,如果共享内存里面的数据被消费调了,则发送该事件

2.增加发送数据的长度,当读取到的总数据长度等于发送的长度时,调用数据处理函数

 

三、代码

ShareMemory.h

#ifndef SHAREMEMORY_H
#define SHAREMEMORY_H

#include 
#include 
#include 
#include 
#include "Windows.h"


class ShareMemory
{
public:
	ShareMemory(std::wstring strKey, unsigned int nSize = 1024);
	~ShareMemory();

	void registeReceiver(std::function pfunReceiver);
	void writeData(char *data, unsigned int nLength);

private:
	void readData();
	void int2Bytes(int nValue, int nLength, unsigned char* pResult);
	int	bytes2Int(unsigned char* pData, int nLength);

private:
	std::shared_ptr m_ptrReadThread;
	bool m_bThreadRunning = true;

	HANDLE m_hMapFile = nullptr;
	LPVOID m_buffer = nullptr;
	unsigned int m_nBufferSize;

	std::function m_pfunReceiver = nullptr;
	
	std::wstring m_strUniqueId;
	HANDLE m_writeEvent = nullptr;
	HANDLE m_readEvent = nullptr;
};

#endif

ShareMemory.cpp

#include "stdafx.h"
#include "ShareMemory.h"
#include 


ShareMemory::ShareMemory(std::wstring strKey, unsigned int nSize) : m_nBufferSize(nSize)
{
	m_strUniqueId = std::move(strKey);
	m_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, m_strUniqueId.c_str());
	if (!m_hMapFile)
	{
		m_hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, m_nBufferSize, m_strUniqueId.c_str());
	}

	if (m_hMapFile)
	{
		m_buffer = MapViewOfFile(m_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, m_nBufferSize);

		if (!m_buffer)
		{
			CloseHandle(m_hMapFile);
		}
		else
		{
			
			
			std::wstring strWriteKey = m_strUniqueId;
			strWriteKey.append(L"_write");
			m_writeEvent = CreateEvent(NULL, TRUE, FALSE, strWriteKey.c_str());

			std::wstring strReadKey = m_strUniqueId;
			strReadKey.append(L"_read");
			m_readEvent = CreateEvent(NULL, TRUE, FALSE, strReadKey.c_str());
			
			if (m_readEvent)
			{
				SetEvent(m_readEvent);
			}

			memset(m_buffer, 0, m_nBufferSize);
			m_ptrReadThread = std::make_shared(std::bind(&ShareMemory::readData, this));
		}
	}
}


ShareMemory::~ShareMemory()
{
	if (m_buffer)
	{
		UnmapViewOfFile(m_buffer);
		m_buffer = nullptr;
	}

	if (m_hMapFile)
	{
		CloseHandle(m_hMapFile);
		m_hMapFile = nullptr;
	}

	if (m_writeEvent)
	{
		CloseHandle(m_writeEvent);
		m_writeEvent = nullptr;
	}
	
	if (m_readEvent)
	{
		CloseHandle(m_readEvent);
		m_readEvent = nullptr;
	}
}

void ShareMemory::registeReceiver(std::function pfunReceiver)
{
	m_pfunReceiver = pfunReceiver;
}

void ShareMemory::writeData(char *data, unsigned int nLength)
{
	if (!m_writeEvent || !m_readEvent)
	{
		return;
	}

	
	unsigned char *sendData = (unsigned char *)malloc(4 + nLength);
	if (!sendData)
	{
		//内存申请失败
		return;
	}

	char lenHead[4] = { 0 };
	int2Bytes(nLength, 4, sendData);
	memcpy(sendData + 4, data, nLength);
	nLength += 4;

	int nAlreadySendSize = 0;

	while (nLength > 0)
	{
		DWORD  dwWaitResult = WaitForSingleObject(m_readEvent, INFINITE);
		switch (dwWaitResult)
		{
		// Event object was signaled
		case WAIT_OBJECT_0:
		{
			unsigned int nSendSize = nLength < m_nBufferSize ? nLength : m_nBufferSize;
			memcpy(m_buffer, sendData + nAlreadySendSize, nSendSize);
			nAlreadySendSize += nSendSize;
			nLength -= nSendSize;
			ResetEvent(m_readEvent);
			SetEvent(m_writeEvent);
			break;
		}
		}
	}
	
	//释放内存
	delete sendData;
	sendData = nullptr;
}

void ShareMemory::readData()
{
	if (!m_writeEvent || !m_readEvent)
	{
		return;
	}

	unsigned int nReveiceLen = 0;
	unsigned int nSendLen = 0;
	unsigned char *dataBegin = nullptr;

	while (m_bThreadRunning)
	{
		DWORD  dwWaitResult = WaitForSingleObject(m_writeEvent, INFINITE);
		switch (dwWaitResult)
		{
			// Event object was signaled
		case WAIT_OBJECT_0:
		{
			if (m_pfunReceiver)
			{
				unsigned char *data = (unsigned char*)m_buffer;

				if (nSendLen == 0)
				{
					nSendLen = bytes2Int(data, 4);
					nReveiceLen = nSendLen > m_nBufferSize - 4 ? m_nBufferSize - 4 : nSendLen;
					dataBegin = (unsigned char*)malloc(nSendLen + 1);
					memset(dataBegin, 0, nSendLen + 1);
					memcpy(dataBegin, data + 4, nReveiceLen);
					memset(m_buffer, 0, nReveiceLen + 4);
				}
				else
				{				
					int nLen = nReveiceLen + m_nBufferSize > nSendLen ? (nSendLen - nReveiceLen) : m_nBufferSize;
					memcpy(dataBegin + nReveiceLen * sizeof(unsigned char), data, nLen);
					nReveiceLen += nLen;
					memset(m_buffer, 0, nLen);
				}

				if (nReveiceLen >= nSendLen)
				{
					m_pfunReceiver(dataBegin, nSendLen);
					nReveiceLen = 0;
					nSendLen = 0;
					delete dataBegin;
					dataBegin = nullptr;
				}
				
				
				ResetEvent(m_writeEvent);
				SetEvent(m_readEvent);
			}
			break;
		}

		default:
			std::cout<<"Wait error :" << GetLastError()<> 8 * (3 - i) & 0xFF);
	}
}

int ShareMemory::bytes2Int(unsigned char* pData, int nLength)
{
	if (pData == NULL)
	{
		return 0;
	}
	int nValue = 0;
	for (int i = 0; i < nLength; i++) {
		nValue += (pData[i] & 0xFF) << (8 * (3 - i));
	}
	return nValue;
}

 

你可能感兴趣的:(C++)