首页 > C/C++ > VC共享内存的使用
2015
03-20

VC共享内存的使用

主要用途是从服务端实时接收到客户端写到共享内存的东西。

头文件
SharedMemoryT.h

// dnybz [3/20/2015]
#pragma once
#include <string>
#include <Windows.h>

#define  MEM_NAME L"Local\\MMemoryObject_0"
#define  MEM_MUTEX L"MMemoryMutex"

typedef BOOL (*TraceCallBack)(unsigned long uProcessId, const char* pString, DWORD nSize);

// 数据结构可以自己定义
struct TSharedMemory {
	unsigned long ProcessId;    // 客户端进程ID
	char Text[512];			// 从服务器到客户端的文本
	int Length;					// 文本长度
};

class SharedMemoryT
{

protected:
	SharedMemoryT();
private:
	SharedMemoryT(const SharedMemoryT& sm)
	{

	}
	SharedMemoryT& operator= (const SharedMemoryT& sm)
	{

	}
public:
	virtual ~SharedMemoryT(void);
public:
	///得到的唯一实例对象
	static SharedMemoryT& Instance();
	///写数据
	bool WriteSharedMemory(const std::string szValue);
	void RegisterCallback(TraceCallBack callback);

private:
	DWORD m_dwProcessId;
	HANDLE m_hMap;
};

 

源文件
SharedMemoryT.cpp

#include "SharedMemoryT.h"

BOOL m_bServer;           // 服务器或客户机实例
HANDLE m_hExecute;      // 客户端通知服务器
HANDLE m_hDone;         // 服务器通知客户
HANDLE m_hMutex;        // 互斥同步的客户
TSharedMemory *g_SharedMemory; 
TraceCallBack	g_CallBack;

// 定时器回调函数  
void CALLBACK TimeProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime);  
// 线程回调函数  
DWORD CALLBACK ThreadProc(PVOID pvoid); 

SharedMemoryT::SharedMemoryT()
{
	m_bServer = FALSE;
	m_hExecute = NULL;
	m_hDone = NULL;
	m_hMutex = NULL;
	g_SharedMemory = NULL;
	m_dwProcessId = ::GetCurrentProcessId();

	// 尝试创建文件映射对象(假设这是服务器)
	m_hMap = ::CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,
		sizeof(TSharedMemory),
		MEM_NAME);

	// 检查文件映射对象已经存在。如果是这样,那么这是一个
	// 客户端在这种情况下打开现有的文件映射对象。客户端还
	// 需要创建一个互斥对象来同步访问服务器
	if (GetLastError() == ERROR_ALREADY_EXISTS) {
		m_hMap = ::OpenFileMapping(FILE_MAP_WRITE,FALSE, MEM_NAME);
		m_hMutex = ::CreateMutex(NULL,FALSE, MEM_MUTEX);
	} else {
		m_bServer = TRUE;
	}

	// 从到文件映射对象句柄获得一个指针
	g_SharedMemory = (TSharedMemory*)::MapViewOfFile(m_hMap,FILE_MAP_WRITE,0,0,sizeof(TSharedMemory));

	// 创建与服务器进行通信的事件
	m_hExecute = ::CreateEvent(NULL, FALSE, FALSE, L"ShareMemoryExecute");
	m_hDone = ::CreateEvent(NULL, FALSE, FALSE, L"ShareMemoryDone");

	//
	if (m_bServer) {
		DWORD dwThreadId;  
		// 创建线程  
		HANDLE hThread = CreateThread(NULL, 0, ThreadProc, 0, 0, &dwThreadId); 
	}
}
SharedMemoryT& SharedMemoryT::Instance()
{
	static SharedMemoryT sm;
	return sm;
}
SharedMemoryT::~SharedMemoryT(void)
{
	if (m_bServer)
		 KillTimer(NULL, 10);

	::CloseHandle(m_hExecute);
	::CloseHandle(m_hDone);
	if (m_hMutex)
		::CloseHandle(m_hMutex);

	::UnmapViewOfFile(g_SharedMemory);
	::CloseHandle(m_hMap);
}

// 写共享内存 - 客户端
bool SharedMemoryT::WriteSharedMemory(const std::string szValue)
{
	bool bRet;
	//等待互斥。一旦获得,没有其他的客户可能与服务器通信
	if (::WaitForSingleObject(m_hMutex, 250) == WAIT_OBJECT_0) {
		g_SharedMemory->ProcessId = ::GetCurrentProcessId();
		strcpy(g_SharedMemory->Text, szValue.c_str());
		g_SharedMemory->Length = szValue.length();

		// 处理服务器的反回信号
		::SetEvent(m_hExecute);
		// 等待服务器完成
		if (::WaitForSingleObject(m_hDone, 250) == WAIT_OBJECT_0) {
			// 服务器完成数据处理,处理服务器返回的数据
			bRet = true;
		} else {
			// 服务器响应超时
			bRet = false;
		}
		// 释放互斥体
		::ReleaseMutex(m_hMutex);
	}
	return bRet;
}

// 接收信息服务端
void CALLBACK TimeProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)  
{  
	if (::WaitForSingleObject(m_hExecute, 10) == WAIT_OBJECT_0) {
		// 设置一个回调
		if (g_CallBack)
			g_CallBack(g_SharedMemory->ProcessId, g_SharedMemory->Text, g_SharedMemory->Length);
		::SetEvent(m_hDone);
	}
}  

DWORD CALLBACK ThreadProc(PVOID pvoid)  
{  
	MSG msg;  
	PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);   
	::SetTimer(NULL, 10, 100, TimeProc);  
	while(GetMessage(&msg, NULL, 0, 0))  
	{  
		if(msg.message == WM_TIMER)  
		{  
			TranslateMessage(&msg);    // 翻译消息  
			DispatchMessage(&msg);     // 分发消息  
		}  
	}  
	KillTimer(NULL, 10);  
	return 0;  
}  

void SharedMemoryT::RegisterCallback(TraceCallBack callback)
{  
	g_CallBack = callback; //将要回调的函数首地址赋值给你的指针变量  
}

 

服务端代码

// SharedMemoryTest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "SharedMemoryT.h"

BOOL OnTracer(unsigned long uProcessId, const char* pString, DWORD nSize)
{
	char buf[MAX_PATH*2] = {0};
	sprintf(buf, "客户端进程Id: %d 文本: %s 长度: %d", uProcessId, pString, nSize);
	puts(buf);
	return TRUE;
}

int _tmain(int argc, _TCHAR* argv[])
{
	SharedMemoryT& sm = SharedMemoryT::Instance();

	// 注册一个回调接收消息
	sm.RegisterCallback(OnTracer);
	puts("当前为服务端");
	
	MSG   msg ;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg) ;
		DispatchMessage(&msg) ;
	}

	return 0;
}

 

客户端代码

// SharedMemoryTest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "SharedMemoryT.h"

int _tmain(int argc, _TCHAR* argv[])
{
	SharedMemoryT& sm = SharedMemoryT::Instance();
	puts("当前为客户端");
	for(int i = 0; i < 10 ;i++)
	{
		sm.WriteSharedMemory("这是一条消息从客户端!");
	}

	MSG   msg ;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg) ;
		DispatchMessage(&msg) ;
	}

	return 0;
}

 

运行效果

最后编辑:
作者:dnybz
这个作者貌似有点懒,什么都没有留下。