一、问题:
上篇文章留下了一些问题,这次主要解决以下两个问题:
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;
}