大家都知道进程之间的通信可以使用共享内存,但是在具体代码中如何实现呢?下面就介绍下操作原理和我自己的实现代码。
在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
);
源码:
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.截图
服务端发送数据:
客户端接收数据:
5.注意
(1.)由于事件,信号,互斥对象和文件映射等这些内核对象都共享同一个名字空间,所以如果这个名字和其他一个对象的名称重名的话那么将创建失败。
(2.)为了实现共享内存,进程应首先调用CreateFileMapping函数然后在hFile参数中传入INVALID_HANDLE_VALUE宏来替代句柄。相应的文件映射对象会从系统的分页文件中获得一段内存。如果hFile参数的值是INVALID_HANDLE_VALUE,那么你在调用CreateFileMapping时必须给共享内存指定一个大小值。