进程的通信 - 邮槽

邮槽

邮槽是Windows系统提供的一种单向进程间的通信机制。对于相对简短的地坪率信息发送,使用邮槽通常比命名管道或者Unix域套接字更简单    

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

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

    通过邮槽通信的数据可以是任意格式的,但是一条消息不能大于424字节

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

过程

1.服务端通过CreateMailslot创建一个邮槽

2.客户端通过CreateFile与邮槽连接

3.客户端通过WritrFile写入数据

4.服务端通过ReadFile读数据

邮槽通信常用的API接口

CreateMailslot函数

HANDLE CreateMailslot(
  [in]           LPCWSTR               lpName,
  [in]           DWORD                 nMaxMessageSize,
  [in]           DWORD                 lReadTimeout,
  [in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
  • 参数lpName

指定邮槽的名称

邮槽的名称:

  • \\\\.\\mailslot\\[path\\]name–> 本机

  • \\\\DomainName\\[path\\]name–> 网络域名

  • \\\\ComputerName\\[path\\]name–> 网络计算机名

  • \\\\*\\mailslot\\[path\\]name –> 广播

此案例将利用邮槽来实现两个进程间的通信,选择第一个名称

  • 参数nMaxMessageSize 

可以写入邮槽的单个消息的最大大小(字节,0表示可以是任意大小

  • 参数IReadTimeout

可以等待消息写入邮槽的事件,0表示没有消息立即返回;MAILSLOT_WAIT_FOREVER表示永远等待

函数成功返回邮件槽的句柄,失败则返回INVALID_HANDLE_VALUE。

CreateMailslotW function (winbase.h) - Win32 apps |微软学习 (microsoft.com)

ReadFile函数

BOOL ReadFile(
  [in]                HANDLE       hFile,
  [out]               LPVOID       lpBuffer,
  [in]                DWORD        nNumberOfBytesToRead,
  [out, optional]     LPDWORD      lpNumberOfBytesRead,
  [in, out, optional] LPOVERLAPPED lpOverlapped
);
  • 参数hFile

设备句柄

  • 参数lpBuffer

 接收数据缓冲区的指针

  • 参数nNumberOfBytesToRead

读取的最大字节数

  • 参数lpNumberOfBytesRead

指向变量的指针,用来接收使用同步hFile参数读取的字节数。

  • 参数lpOverlapped 

重叠结构的指针,使用FILE_OVERLAPPED打开hFile参数,则为必须,否则可为NNULL

ReadFile function (fileapi.h) - Win32 apps |微软学习 (microsoft.com)

CreateFile 

HANDLE CreateFile(
  [in]           LPCWSTR               lpFileName,
  [in]           DWORD                 dwDesiredAccess,
  [in]           DWORD                 dwShareMode,
  [in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  [in]           DWORD                 dwCreationDisposition,
  [in]           DWORD                 dwFlagsAndAttributes,
  [in, optional] HANDLE                hTemplateFile
);
  • 参数lpFileName

要创建或打开的文件或设备的名称。这里填入邮槽名

  • 参数dwDesiredAccess

对文件或设备的访问方式,可以分为读、写、两者或两者都不是

  • 参数dwShareMode

请求共享模式,可以读取、写入、两者、删除、所有这些或 无。

取值含义

0

0x00000000

防止其他进程在请求删除、读取或写入访问权限时打开文件或设备。

FILE_SHARE_DELETE

0x00000004

对文件或设备启用后续打开操作以请求删除访问权限。

否则,如果其他进程请求删除访问权限,则无法打开文件或设备。

如果未指定此标志,但已打开文件或设备以进行删除访问,则函数 失败。

注意删除访问权限允许删除和重命名操作。
 

FILE_SHARE_READ

0x00000001

启用对文件或设备的后续打开操作以请求读取访问权限。

否则,如果其他进程请求读取访问权限,则无法打开文件或设备。

如果未指定此标志,但文件或设备已打开以进行读取访问,则函数 失败。

FILE_SHARE_WRITE

0x00000002

允许对文件或设备执行后续打开操作以请求写入访问权限。

否则,如果其他进程请求写入访问权限,则无法打开文件或设备。

如果未指定此标志,但文件或设备已打开以进行写入访问或具有文件映射 使用写入访问权限时,函数将失败。

  • 参数lpSecurityAttributes

 安全描述符,为NULL表示任何子进程都不能继承CreateFile返回的句柄。

  • 参数dwCreationnDisposition

对存在或不存在的文件或设备执行的操作。

对于文件以外的设备,此参数通常设置为OPEN_EXISTING

  • 参数dwFlagAndAttrubutes

文件或设备属性和标志,FILE_ATTRIBUTE_NORMAL是最多的 文件的通用默认值。

  • 参数hTemplateFile

此参数可以为NULL。

CreateFileW 函数 (fileapi.h) - Win32 apps |微软学习 (microsoft.com)

BOOL WriteFile(
  [in]                HANDLE       hFile,
  [in]                LPCVOID      lpBuffer,
  [in]                DWORD        nNumberOfBytesToWrite,
  [out, optional]     LPDWORD      lpNumberOfBytesWritten,
  [in, out, optional] LPOVERLAPPED lpOverlapped
);
  •  参数hFile

文件或设备句柄

  • 参数lpBuffer

写入数据的缓冲区指针

  • 参数nNumberOfBytesToWrote

写入文件或设备的字节数

  • 参数lpNumberOfBytesWritten

指向变量的指针,该变量接收使用同步hFile参数时写入的字节数。

  • 参数lpOverlapped

指向重叠结构的指针是 如果使用FILE_FLAG_OVERLAPPED 打开hFile参数,则为必需,否则此参数可以为NULL。

如果函数成功,则返回值为非零值 (TRUE),如果函数失败或异步完成,则返回值为零(FALSE)。

WriteFile function (fileapi.h) - Win32 apps |微软学习 (microsoft.com)

Demo示例

两个基于单个对话框的MFC应用

aa0d8fa65acd451f9c22b0e1dc77f297.png

79f881a6f1fc44cc962fa01aae67c92e.png

在菜单栏中点击“服务端”,响应函数创建一个邮槽,然后开始永远等待消息的到来,将接收到的消息通过提示框显示出来

在菜单栏中点击“发送数据”,响应函数会与邮槽连接,并向邮槽写入数据

服务端 

void CChildView::OnSlot()
{
	//邮槽名 "\\.\mailslot\Mymailslot"
	//1.创建一个邮槽
	LPCTSTR szSlotName = TEXT("\\\\.\\mailslot\\Mymailslot");
	HANDLE hSlot;
	hSlot = CreateMailslot(szSlotName,
		0,	//最大消息大小的限制
		MAILSLOT_WAIT_FOREVER, //无超时操作
		(LPSECURITY_ATTRIBUTES)NULL	//默认安全
	);
	//判断创建的邮槽是否有效
	if (hSlot == INVALID_HANDLE_VALUE) {
		//如果创建的邮槽是一个无效的句柄
		TRACE("CreateMailslot failed with %d\n", GetLastError());
		return;
	}
	//2.读数据
	char szBuf[100] = { 0 };
	DWORD dwRead;
	//阻塞在这里 
	if (!ReadFile(hSlot, szBuf, 100, &dwRead, NULL)) {
		MessageBox(_T("读取失败"));
		CloseHandle(hSlot);
		//return;
	}
	else {
		MessageBox((CStringW)szBuf);
	}
}

发送数据

void CChildView::OnSend()
{
	LPCTSTR szSlotName = TEXT("\\\\.\\mailslot\\Mymailslot");
	//创建一个文件句柄
	HANDLE hMailSlot = CreateFile(szSlotName,
		FILE_GENERIC_WRITE,//权限
		FILE_SHARE_READ,//共享模式
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL
	);

	if (hMailSlot == INVALID_HANDLE_VALUE) {
		TRACE("CreateFile failed with %d\n", GetLastError());
		return;
	}
	//写入数据
	char szBuf[] = "北极熊猫很handsome";
	DWORD dwWrite;
	if (!WriteFile(hMailSlot, szBuf, strlen(szBuf) + 1, &dwWrite, NULL)) {
		MessageBox(_T("写入数据失败"));
		CloseHandle(hMailSlot);
		return;
	}
	CloseHandle(hMailSlot);
}

执行结果:

先点击左端应用的“服务端”,然点点击右端“发送数据”,左端应用将接收到的数据显示出来。

79e60772c96a4f45a6aeff32958fa5f1.gif

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值