20、Windows API 进程间通信,邮槽(Mailslot)-阿里云开发者社区

开发者社区> hopegrace> 正文

20、Windows API 进程间通信,邮槽(Mailslot)

简介:     进程的地址空间是私有的。出于安全性的目的,如果一个进程不具有特殊的权限,是无法访问另外一个进程的内存空间的,也无法知道内存中保存的数据的意义。但是在一些具体的应用情况下需要多个进行相互配合,有时计算机用户也需要在多个应用程序之间交换数据。
+关注继续查看

    进程的地址空间是私有的。出于安全性的目的,如果一个进程不具有特殊的权限,是无法访问另外一个进程的内存空间的,也无法知道内存中保存的数据的意义。但是在一些具体的应用情况下需要多个进行相互配合,有时计算机用户也需要在多个应用程序之间交换数据。

Windows系统下,在进程间通信或共享数据的方式如下。

◇邮槽(Mailslot)

    邮槽是最为简单的进程间数据共享方式,一个进程创建并拥有一个邮槽,其他进程都可以打开这个邮槽并向其发送消息。

◇管道(Pipe)

实质是一种共享的内存,由一个进程创建,其他进程连接,并可进行双向的通信。

◇剪贴板(Clipboard)

    剪贴板是重要的进程间数据共享方式,所有的进程都可以设置和修改剪贴板,也都可以从剪贴板获取内容。

◇消息,具体是指WM_COPYDATA消息。

消息具有参数wParamlParam。但是wParamlParam最多是32位的。而WM_COPYDATA消息的参数不受wParamlParam数据大小的限制,可以用于在进程间传递数据。

◇网络。

    网络可以在不同主机上的不同程序间通信,当然也可以在相同主机上的不同程序间通信。

FileMapping[2]

一、邮槽(MailSlot)

    使用邮槽通信的进程分为服务端和客户端。邮槽由服务端创建,在创建时需要指定邮槽名,创建后服务端得到邮槽的句柄。在邮槽创建后,客户端可以通过邮槽名打开邮槽,在获得句柄后可以向邮槽写入消息。

    邮槽通信是单向的,只有服务端才能从邮槽中读取消息,客户端只能写入消息。消息是先入先出的。客户端先写入的消息在服务端先被读取。

通过邮槽通信的数据可以是任意格式的,但是一条消息不能大于424字节。邮槽除了在本机内进行进程间通信外,在主机间也可以通信。但是在主机间进行邮槽通信,数据通过网络传播时使用的是数据报协议(UDP),所以是一种不可靠的通信。通过网络进行邮槽通信时,客户端必须知道服务端的主机名或域名。

MailSlot的详细介绍,可以参见[3],[4]也作了一些介绍。

邮槽通信服务端程序

img_1c53668bcee393edac0d7b3b3daff1ae.gif通过mailslot进程间通信-服务端

通过mailslot进程间通信
**************************************/
/* 头文件 */
#include
<windows.h>
#include
<stdio.h>
/* 全局变量 */
HANDLE hSlot;
LPTSTR lpszSlotName
= TEXT("\\\\.\\mailslot\\sample_mailslot");
LPTSTR Message
= TEXT("Message for mailslot in primary domain.");

/* ************************************
* void main()
* 功能 进程间mailslot通信客户端
*************************************
*/
void main()
{
DWORD cbMessage, cMessage, cbRead;
BOOL fResult;
LPTSTR lpszBuffer;
TCHAR achID[
80];
DWORD cAllMessages;
HANDLE hEvent;
OVERLAPPED ov;

cbMessage
= cMessage = cbRead = 0;

hSlot
= CreateMailslot(
lpszSlotName,
// mailslot 名
0, // 不限制消息大小
MAILSLOT_WAIT_FOREVER, // 无超时
(LPSECURITY_ATTRIBUTES) NULL);

if (hSlot == INVALID_HANDLE_VALUE)
{
printf(
"CreateMailslot failed with %d\n", GetLastError());
return ;
}
else printf("Mailslot created successfully.\n");

while(1)
{
// 获取mailslot信息
fResult = GetMailslotInfo(hSlot, // mailslot 句柄
(LPDWORD) NULL, // 无最大消息限制
&cbMessage, // 下一条消息的大小
&cMessage, // 消息的数量
(LPDWORD) NULL); // 无时限

if (!fResult)
{
printf(
"GetMailslotInfo failed with %d.\n", GetLastError());
return ;
}

if (cbMessage == MAILSLOT_NO_MESSAGE)
{
// 没有消息,过一段时间再去读
Sleep(20000);
continue;
}

cAllMessages
= cMessage;

while (cMessage != 0) // 获取全部消息,有可能不只一条
{
// 提示信息
wsprintf((LPTSTR) achID,
"\nMessage #%d of %d\n",
cAllMessages
- cMessage + 1,
cAllMessages);

// 分配空间
lpszBuffer = (LPTSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
lstrlen((LPTSTR) achID)
*sizeof(TCHAR) + cbMessage);
if( NULL == lpszBuffer )
{
return ;
}
// 读取消息
fResult = ReadFile(hSlot, // mailslot句柄
lpszBuffer, // 缓存
cbMessage, // 消息的长度
&cbRead, // 实际读取的长度
NULL);

if (!fResult)
{
printf(
"ReadFile failed with %d.\n", GetLastError());
GlobalFree((HGLOBAL) lpszBuffer);
return ;
}

// 处理信息,显示
lstrcat(lpszBuffer, (LPTSTR) achID);
printf(
"Contents of the mailslot: %s\n", lpszBuffer);

HeapFree(GetProcessHeap(),
0,lpszBuffer);
// 计算剩余的消息数
fResult = GetMailslotInfo(hSlot,
(LPDWORD) NULL,
&cbMessage,
&cMessage,
(LPDWORD) NULL);

if (!fResult)
{
printf(
"GetMailslotInfo failed (%d)\n", GetLastError());
return ;
}
}
}
return ;
}

邮槽通信客户端程序

img_1c53668bcee393edac0d7b3b3daff1ae.gif通过mailslot进程间通信-客户端

通过mailslot进程间通信
**************************************/
/* 头文件 */
#include
<windows.h>
#include
<stdio.h>
/* 全局变量 */
HANDLE hSlot;
LPTSTR lpszSlotName
= TEXT("\\\\.\\mailslot\\sample_mailslot"); // mailslot名
LPTSTR lpszMessage = TEXT("Test Message for mailslot "); // 通信的内容

/* ************************************
* void main()
* 功能 进程间mailslot通信客户端
*************************************
*/
void main()
{
BOOL fResult;
HANDLE hFile;
DWORD cbWritten;

DWORD cbMessage;
// 打开mailslot
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写入
fResult = WriteFile(hFile,
lpszMessage,
(DWORD) (lstrlen(lpszMessage)
+1)*sizeof(TCHAR),
&cbWritten,
(LPOVERLAPPED) NULL);

if (!fResult)
{
printf(
"WriteFile failed with %d.\n", GetLastError());
return ;
}
// 结束
printf("Slot written to successfully.\n");
CloseHandle(hFile);
return ;
}

参考

[1] 精通Windows API 函数、接口、编程实例

[2] http://www.cnblogs.com/mydomain/archive/2011/01/07/1929874.html

[3] http://msdn.microsoft.com/en-us/library/aa365130%28VS.85%29.aspx

[4] http://www.cnblogs.com/mydomain/archive/2010/09/18/1830476.html?login=1

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
WinCE下如何获取进程所在的目录
  众所周知,WinCE下没有当前目录的概念,所有路径都以根目录"\\"为参考。获取进程所在目录的参考代码如下。 1     GetModuleFileName(NULL,gszPath,MAX_PATH);2     int len = wcslen(gszPath);3     TCH...
487 0
windows下bat批处理实现守护进程
本文转自网络,由于找不到原作者,因而无法知道出处。如果有幸让原作者看到,请联系我加上。先转载至此。 最近几天加班加疯掉了,天天晚上没法睡。开发部的一个核心程序总是会自己宕机,然后需要手工去起,而这个服务的安全级别又很高,只有我可以操作,搞得我晚上老没法睡,昨晚实在受不了了,想起以前在hp-ux下写的shell守护进程,这回搞个windows下的bat版守护程序吧,当时晚上思路已经很迟钝了,就叫了个兄弟让他写了,上去后运行效果不错,至少昨晚我安心睡了7小时。
451 0
windows api学习笔记-读写其他进程的内存
#include #include using namespace std; HANDLE g_hProcess; BOOL ChangeMemory(DWORD dwValue) { const DWORD dwOneGB = 1024*1024*1024;//1GB...
608 0
windows api学习笔记-遍历系统进程,获取进程名称和ID(进程快照)
#include //系统会自动连接到指定的库文件lib #include //声明快照函数的头文件 #include //std io 标准输入输出接口 #include using namespace std; int main() { PROCESSENTRY32 pe32; pe32.
784 0
Qt之进程间通信(Windows消息)
简述 通过上一节的了解,我们可以看出进程通信的方式很多,今天分享下如何利用Windows消息机制来进行不同进程间的通信。 简述 效果 发送消息 自定义类型与接收窗体 发送数据 接收消息 设置标题 重写nativeEvent 更多参考 效果 发送消息 自定义类型与接收窗体 包含所需库,定义发送的自定义类型、接收消息的窗体标
1093 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
3956 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
5676 0
+关注
582
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载