C/C++ 日常学习总结(第二十二篇)共享内存实现C++

大家都知道进程之间的通信可以使用共享内存,但是在具体代码中如何实现呢?下面就介绍下操作原理和我自己的实现代码。

在linux下使用的是shmget,shmat,shmdt等函数,所以在网上看到这类的,基本就是在介绍linux环境下的实现,windows下不适用,但可以看其原理。


0.传输数据的结构定义

struct Splayer 
{
	int numid;
	int age;
	char sex;
	char name[128];
	char ip[256];
	int  port;
};

上面结构的定义较为简单,仅为了测试使用。


1.我们会创建两个程序,一个称之服务端,一个称之客户端。

服务端:(1.)创建共享内存区域  (2.)内存映射到当前进程 (3.)写入数据

客户端:(1.)打开共享内存区域  (2.)内存映射到当前进程 (4.)读出数据


2.服务端

void CMySharedServerDlg::MySharedMemory()
{
	/*
	struct Splayer 
	{
	int numid;
	int age;
	char sex;
	char name[128];
	char ip[256];
	int  port;
	};
	*/
	//1.创建共享内存区域
	HANDLE hfile = ::CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,65536,"GameQueen");
	if(NULL==hfile)
	{
		AfxMessageBox("创建失败!",MB_OK,0);
		return;
	}

	//2.内存映射
	PVOID pview = NULL;
	pview = ::MapViewOfFile(hfile,FILE_MAP_ALL_ACCESS,0,0,1024);
	if (NULL==pview)
	{
		AfxMessageBox("映射失败!",MB_OK,0);
		return;
	}

	//char* pMessage = "皇后come from MySharedServerDlg!";//单独字符串也可传输
	
	Splayer player;
	player.numid = 6666;
	player.age = 24;
	player.sex = '1';
	strcpy(player.name,"tangwei");
	strcpy(player.ip,"192.168.1.102");
	player.port = 8080;
	DWORD dmessage = sizeof(Splayer);

	memcpy_s(pview,1024,&player,dmessage);

}
上面是源码,简诉下过程:

(1)、创建一个特定大小的文件映射对象,名称为“GameQueen”,也可以宏来定义。

(2)、将这个对象的文件视图映射到进程的地址空间,然后向视图中写入数据/字符串。

(3)、函数参数分析     

// Create the file mapping object.
    hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,   // Use paging file - shared memory
        NULL,                   // Default security attributes
        PAGE_READWRITE,         // Allow read and write access
        0,                      // High-order DWORD of file mapping max size
        MAP_SIZE,               // Low-order DWORD of file mapping max size
        FULL_MAP_NAME           // Name of the file mapping object
        );

pView = MapViewOfFile(
        hMapFile,               // Handle of the map object
        FILE_MAP_ALL_ACCESS,    // Read and write access
        0,                      // High-order DWORD of the file offset 
        VIEW_OFFSET,            // Low-order DWORD of the file offset 
        VIEW_SIZE               // The number of bytes to map to view
        );

3.客户端

源码:

void CMyShareClientDlg::MySharedMemory()
{
	HANDLE hfile = OpenFileMapping(FILE_MAP_READ,FALSE,"GameQueen");
	if (NULL==hfile)
	{
		AfxMessageBox("不能打开共享内存",MB_OK,0);
		return;
	}
	PVOID pview;
	pview = ::MapViewOfFile(hfile,FILE_MAP_READ,0,0,1024);
	if (NULL==pview)
	{
		AfxMessageBox("不能打开2",MB_OK,0);
		return;
	}
	//char*  pStr = (char*)pview;
	//CString str(pStr);
	//OutputDebugString(str);
	Splayer *player = (Splayer*)pview;//上面读取字符串,此处是读取结构体信息
}

过程分析:

(1.)执行客户程序CMyShareClientDlg

(2.)打开这个名称为“GameQueen”的文件映射对象

(3.)然后把相同的文件映射视图映射到自己的地址空间中

(4.)然后从视图中读取服务进程所写入的数据。


4.截图

服务端发送数据:

C/C++ 日常学习总结(第二十二篇)共享内存实现C++_第1张图片

客户端接收数据:

C/C++ 日常学习总结(第二十二篇)共享内存实现C++_第2张图片


5.注意

(1.)由于事件,信号,互斥对象和文件映射等这些内核对象都共享同一个名字空间,所以如果这个名字和其他一个对象的名称重名的话那么将创建失败。

(2.)为了实现共享内存,进程应首先调用CreateFileMapping函数然后在hFile参数中传入INVALID_HANDLE_VALUE宏来替代句柄。相应的文件映射对象会从系统的分页文件中获得一段内存。如果hFile参数的值是INVALID_HANDLE_VALUE,那么你在调用CreateFileMapping时必须给共享内存指定一个大小值。


你可能感兴趣的:(C++日常学习总结)