博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Win]进程间通信——邮槽Mailslot
阅读量:4631 次
发布时间:2019-06-09

本文共 3749 字,大约阅读时间需要 12 分钟。

进程间通信

进程的地址空间是私有的。出于安全性的目的,如果一个进程不具有特殊的权限,是无法访问另外一个进程的内存空间的,也无法知道内存中保存的数据的意义。但是在一些具体的应用情况下需要多个进行相互配合,有时计算机用户也需要在多个应用程序之间交换数据。
Windows系统下,在进程间通信或共享数据的方式如下。
  • 邮槽( Mailslot)。邮槽是最为简单的进程间数据共享方式,一个进程创建并拥有一个邮槽,其他进程都可以打开这个邮槽并向其发送消息。
  • 管道(Pipe)。实质是一种共享的内存,由一个进程创建,其他进程连接,并可进行双向的通信。
  • 剪贴板( Clipboard)。剪贴板是重要的进程间数据共享方式,所有的进程都可以设置和修改剪贴板,也都可以从剪贴板获取内容。
  • 消息,具体是指WM_COPYDATA消息。消息具有参数wParam和lParam。但是wParam和lParam最多是32位的。而WM_COPYDATA消息的参数不受wParam和lParam数据大小的限制,可以用于在进程间传递数据。
  • 网络。网络可以在不同主机上的不同程序间通信,当然也可以在相同主机上的不同程序间通信。
  • FileMapping. 

邮槽

使用邮槽通信的进程分为服务端和客户端。邮槽由服务端创建,在创建时需要指定邮槽名,创建后服务端得到邮槽的句柄。在邮槽创建后,客户端可以通过邮槽名打开邮槽,在获得句柄后可以向邮槽写入消息。
邮槽通信是单向的,只有服务端才能从邮槽中读取消息,客户端只能写入消息。消息是先入先出的。客户端先写入的消息在服务端先被读取。
通过邮槽通信的数据可以是任意格式的,但是一条消息不能大于424字节。
邮槽除了在本机内进行进程间通信外,在主机间也可以通信。但是在主机间进行邮槽通信,数据通过网络传播时使用的是数据报协议(UDP),所以是一种不可靠的通信。通过网络进行邮槽通信时,客户端必须知道服务端的主机名或域名。

实例

server:
/*进程间mailslot通信服务器端创建了一个名为“\\\\.\\mailslot\\sample_mailslot”的邮槽,然后使用GetMailslotInfo函数读取消息数量。如果没有消息,则等待3s获取信息。循环直至有消息到达,然后一次性读出全部消息。*/#include 
#include
HANDLE hSlot;LPTSTR lpszSlotName = TEXT("\\\\.\\mailslot\\sample_mailslot"); void main(){ DWORD cbMessage, cMessage, cbRead,cAllMessages; BOOL bResult; TCHAR lpszBuffer[1000]; TCHAR achID[80]; cbMessage = cMessage = cbRead = 0; hSlot = CreateMailslot( lpszSlotName, // mailslot 名 0, // 不限制消息大小 MAILSLOT_WAIT_FOREVER, // 无超时 NULL); if (hSlot == INVALID_HANDLE_VALUE) { printf("CreateMailslot failed with %d\n", GetLastError()); return ; } else printf("Mailslot created successfully.\n"); while(1) { // 获取mailslot信息 bResult = GetMailslotInfo(hSlot, // mailslot 句柄 (LPDWORD) NULL, // 无最大消息限制 &cbMessage, // 下一条消息的大小 &cMessage, // 消息的数量 (LPDWORD) NULL); // 无时限 if (!bResult) { printf("GetMailslotInfo failed with %d.\n", GetLastError()); return ; } printf("MAILSLOT_NO_MESSAGE \n"); if (cbMessage == MAILSLOT_NO_MESSAGE) { // 没有消息,过一段时间再去读 Sleep(3000); continue; } printf("has MAILSLOT_NO_MESSAGE\n"); cAllMessages = cMessage; while (cMessage != 0) // 获取全部消息,有可能不只一条 { // 提示信息 wsprintf(achID, "\nMessage #%d of %d\n", cAllMessages - cMessage + 1, cAllMessages); // 读取消息 if(!ReadFile(hSlot,lpszBuffer,cbMessage,&cbRead,NULL)) { printf("ReadFile failed with %d.\n", GetLastError()); return ; } lstrcat(lpszBuffer, achID); //连接 printf("Contents of the mailslot: %s\n", lpszBuffer);//显示 bResult = GetMailslotInfo(hSlot,NULL,&cbMessage,&cMessage,NULL); // 计算剩余的消息数,若cMessage=0,则退出子循环 if (!bResult) { printf("GetMailslotInfo failed (%d)\n", GetLastError()); return ; } } } }
client:
/*进程间mailslot通信客户端客户端向邮槽发送消息需要首先打开邮槽,然后直接使用WriteFile函数写入。打开邮槽使用CreateFile函数。客户端在打开邮槽时需要知道邮槽名。*/#include 
#include
LPTSTR lpszSlotName = TEXT("\\\\.\\mailslot\\sample_mailslot"); // mailslot名LPTSTR lpszMessage = TEXT("Test Message for mailslot "); // 通信的内容void main(){ DWORD cbWritten; DWORD cbMessage; // 打开mailslot HANDLE hFile = CreateFile(lpszSlotName, GENERIC_WRITE, // 可写 FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES) NULL, OPEN_EXISTING, // 打开一个已经存在的mailslot,应该由服务端已经创建 FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("CreateFile failed with %d.\n", GetLastError()); return ; } // 向mailslot写入 int num=50; while(num) { Sleep(2000); num--; if(!WriteFile(hFile, lpszMessage, (DWORD) (lstrlen(lpszMessage)+1), &cbWritten, (LPOVERLAPPED) NULL)) { printf("WriteFile failed with %d.\n", GetLastError()); return ; } printf("Slot written to successfully.\n"); } CloseHandle(hFile); // 结束 }
结果:
参考:

 

转载于:https://www.cnblogs.com/dyllove98/p/3149464.html

你可能感兴趣的文章
机器学习 决策树 ID3
查看>>
Cmake
查看>>
vue 之 nextTick 与$nextTick
查看>>
JS设计模式——3.封装与信息隐藏
查看>>
git-- 使用
查看>>
delphi对窗体的查询(delphi xe2)
查看>>
Ajax跨域:Jsonp原理解析
查看>>
hdu 5099 Comparison of Android versions 枚举题意
查看>>
算法第二章上机实践报告
查看>>
linux--memcache的安装和使用(转)
查看>>
有关于Matlab的regionprops函数的PixelIdxList和PixelList的一点解释
查看>>
Event Loop
查看>>
new做了些什么?
查看>>
BZOJ3835[Poi2014]Supercomputer——斜率优化
查看>>
POJ-1861 Network
查看>>
Java:从字符串文本中获得数字
查看>>
Airbnb的面经复习笔记
查看>>
细说SSO单点登录
查看>>
java操作数据库增删改查的小工具1--TxQueryRunner
查看>>
vs2010统计项目代码总行数
查看>>