Loading... 同一个进程多个线程可以共享进程资源。 ``` 发送WMCOPYDATA消息时,wParam应该保存有发送此消息的窗口句柄,lParam则应该只想一名COPYDATASTRUCT结构体 typedef struct tagCOPYDATASYRUCT { ULOG_PTR dwData; //人一个32位的值 DWORD cbData; //发送数据大小 PVOID lpData; //待发送数据块指针 } ``` 发送消息时,系统会将整个 COPYDATASTRUCT 以及 lpData 所指向的内容发送给目标进程,可以从param中提取数据 # 油槽 进程间通讯方式一个进程可以创建一个油槽 消息被写入油槽后以队列方式保存 除了本机内的进程间通讯 还可以在主机间通讯(UDP协议),如果使用网络油槽通讯,必须要知道服务端主机名或者域名 油槽是单向的,系统中最简单的一种通讯方式 除了本机内进程间通讯外,也可以在主机间进行通讯 | API | 说明 | | - | - | | CreateMailsot | 创建一个油槽 | | GetMailsotInfo | 获取油槽信息 | | CreateFile | 打开文件(打开油槽) | | WriteFile | 写入文件(向油槽写入文件) | | ReadFile | 读取文件(在油槽中读取数据) | | | | ## 服务端 ``` //创建邮槽对象 HANDLE hSlot = CreateMailslot ( L"\\\\.\\mailslot\\Sample", //邮槽名 0, //不限制消息大小 MAILSLOT_WAIT_FOREVER, //无超时 (LPSECURITY_ATTRIBUTES)NULL //安全属性 ); //循环读取邮槽信息 while (true) { //获取邮槽当前消息数量 DWORD dwMsgCount = 0; DWORD dwMsgSize = 0; GetMailslotInfo //获取邮槽信息 ( hSlot, //邮槽句柄 (LPDWORD)NULL, //无最大消息限制 &dwMsgSize, //下一条消息大小 &dwMsgCount, //消息数量 (LPDWORD)NULL //无限时 ); //如果没有消息 if (dwMsgSize == MAILSLOT_NO_MESSAGE) { Sleep(2000); continue; } //循环获取消息如果一直有消息就 while (dwMsgCount) { PBYTE lpBuffer; lpBuffer = new BYTE[dwMsgSize + 0x10]; //读取邮槽中的信息 DWORD dwRet; ZeroMemory(lpBuffer, dwMsgSize); if (!ReadFile(hSlot, lpBuffer, dwMsgSize, &dwRet, NULL)) { printf("ReadFile函数失败,错误码【%d】\n", GetLastError()); delete[]lpBuffer; return 0; } //显示信息 printf("邮槽内容:%s\n", lpBuffer); //计算剩余消息数 这里重新计算了数量 GetMailslotInfo(hSlot, (LPDWORD)NULL, &dwMsgSize, &dwMsgCount, nullptr); delete[]lpBuffer; } } ``` ## 客户端 ``` //1. 打开邮槽 HANDLE hFile = CreateFile ( L"\\\\.\\mailslot\\Sample", //邮槽命令 GENERIC_ALL, //读写属性 FILE_SHARE_READ, //共享属性 NULL, //安全属性 OPEN_EXISTING, //打开方式 FILE_ATTRIBUTE_NORMAL, //标志位 NULL //文件模板 ); //2. 向mailslot写入 DWORD dwWriteLen; LPSTR lpMessage = (LPSTR)"消息邮槽测试!"; DWORD dwMegLen = strlen(lpMessage) + sizeof(CHAR);//后面 0 结尾 WriteFile(hFile, lpMessage, dwMegLen, &dwWriteLen, NULL); //结束 printf("已经向邮槽写入信息!\n"); CloseHandle(hFile); ``` # 文件映射 ## 接收端 ``` //接收端1 HANDLE hFile; //文件句柄 HANDLE hMapFile; //将内存映射到区域文件 LPVOID lpMapAddress;//内在映射区域的起始位置 //1.创建一个文件 hFile = CreateFile(L"C:\\Users\\Administrator\\Desktop\\1.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hFile)return FALSE; //创建文件映射 hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 1024*4*4 ,L"irohane"); if (NULL == hMapFile)return FALSE; //将文件映射回到View lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (NULL == lpMapAddress)return FALSE; while (TRUE) { wchar_t* s = (wchar_t*)lpMapAddress; printf("%s \n", s); Sleep(1000); } // 将映射的数据写回到硬盘上 FlushViewOfFile(lpMapAddress, 0); // 关闭mapping 对象 if (!CloseHandle(hFile))return FALSE; ``` ## 发送端 ``` //发送端 //创建命名的文件映射 HANDLE hmapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 100, L"irohane"); if (hmapFile == NULL || INVALID_HANDLE_VALUE == hmapFile)return FALSE; //创建view PVOID pBuf = MapViewOfFile(hmapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (NULL == pBuf)return FALSE; //将共享数据复制到文件映射中 strcpy_s((char*)pBuf,100, "发送文本"); UnmapViewOfFile(pBuf); CloseHandle(hmapFile); ``` # 内存共享 ``` #include <windows.h> #include <iostream> using namespace std; #define BUF_SIZE 4096 int main() { // 定义共享数据 char szBuffer[] = "www.irohane.top"; // 创建共享文件句柄 HANDLE hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, // 物理文件句柄 NULL, // 默认安全级别 PAGE_READWRITE, // 可读可写 0, // 高位文件大小 BUF_SIZE, // 低位文件大小 L"irohane" // 共享内存名称 ); // 映射缓存区视图 , 得到指向共享内存的指针 LPVOID lpBase = MapViewOfFile( hMapFile, // 共享内存的句柄 FILE_MAP_ALL_ACCESS, // 可读写许可 0, 0, BUF_SIZE ); // 将数据拷贝到共享内存 strcpy((char*)lpBase, szBuffer); // 线程挂起等其他线程读取数据 Sleep(1000); // 解除文件映射 UnmapViewOfFile(lpBase); // 关闭内存映射文件对象句柄 CloseHandle(hMapFile); return 0; } ``` ``` #include <iostream> #include <windows.h> using namespace std; #define BUF_SIZE 4096 int main() { // 打开共享的文件对象 HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, NULL, L"irohane"); if (hMapFile) { LPVOID lpBase = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); // 将共享内存数据拷贝出来 char szBuffer[BUF_SIZE] = { 0 }; strcpy_s(szBuffer, (char*)lpBase); // 解除文件映射 UnmapViewOfFile(lpBase); // 关闭内存映射文件对象句柄 CloseHandle(hMapFile); } else { // 打开共享内存句柄失败 cout << "打开共享失败!" << endl; } return 0; } ``` # 命名管道 命名管道也可以在同一电脑的不同用户下进行通讯,文件映射也可以但是,Win10实验的时候客户端无法打开文件。 ## 服务端 ``` char buf[256] = ""; DWORD rLen = 0; DWORD wLen = 0; HANDLE hPipe = NULL; hPipe = CreateNamedPipe( TEXT("\\\\.\\Pipe\\pipeTest"), //管道名 PIPE_ACCESS_DUPLEX, //管道类型,双向通信 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, //管道参数 PIPE_UNLIMITED_INSTANCES, //管道能创建的最大实例数量 0, //输出缓冲区长度 0表示默认 0, //输入缓冲区长度 0表示默认 NMPWAIT_WAIT_FOREVER, //超时时间,NMPWAIT_WAIT_FOREVER为不限时等待 NULL); //指定一个SECURITY_ATTRIBUTES结构,或者传递零值. if (INVALID_HANDLE_VALUE == hPipe) cout << "创建管道失败: " << GetLastError() << endl; else { cout << "这是命名管道测试程序中的服务器端" << endl; cout << "现在等待客户端连接..." << endl; if (!ConnectNamedPipe(hPipe, NULL)) //阻塞等待客户端连接。 { cout << "连接失败!" << endl; return 1; } else cout << "连接成功!" << endl; if (!ReadFile(hPipe, buf, 256, &rLen, NULL)) //接受客户端发送数据 { cout << "从客户端接收并读取数据!" << endl; return 2; } else cout << "客户端接收的数据为 : " << buf << endl << "数据长度为 " << rLen << endl; char strMessage[] = "命名管道测试程序"; WriteFile(hPipe, strMessage, sizeof(strMessage), &wLen, 0); //向客户端发送数据 CloseHandle(hPipe); //关闭管道句柄 } system("pause"); ``` ## 客户端 ``` cout << "这是命名管道测试程序的客户端" << endl; char buf[256] = ""; DWORD rLen = 0; DWORD wLen = 0; Sleep(1000); //等待管道创建成功! if (!WaitNamedPipe(TEXT("\\\\.\\Pipe\\pipeTest"), NMPWAIT_WAIT_FOREVER)) { cout << "connect the namedPipe failed!" << endl; return 1; } HANDLE hPipe = CreateFile( //创建管道文件,即链接管道 TEXT("\\\\.\\Pipe\\pipeTest"), //管道名称 GENERIC_READ | GENERIC_WRITE, //文件模式 0, //是否共享 NULL, //指向一个SECURITY_ATTRIBUTES结构的指针 OPEN_EXISTING, //创建参数 FILE_ATTRIBUTE_NORMAL, //文件属性,NORMAL为默认属性 NULL); //模板创建文件的句柄 if (INVALID_HANDLE_VALUE == hPipe) { cout << "打开通道失败!" << endl; return 2; } char strMessage[] = "命名管道测试程序"; if (!WriteFile(hPipe, strMessage, sizeof(strMessage), &wLen, 0)) //向管道发送数据 { cout << "向通道写数据失败!" << endl; return 3; } if (!ReadFile(hPipe, buf, 256, &rLen, NULL)) //读取管道数据 { cout << "从通道读数据失败!" << endl; return 4; } else cout << "从服务器端接收数据 : " << buf << endl << "数据长度为:" << rLen << endl; Sleep(1000); //执行挂起一段时间 CloseHandle(hPipe); //关闭管道 system("pause"); ``` 最后修改:2021 年 04 月 26 日 © 允许规范转载 赞 0 如果觉得我的文章对你有用,请随意赞赏
1 条评论
想想你的文章写的特别好https://www.jiwenlaw.com/