📄 17.4 邮槽.txt
字号:
17.4 邮槽
邮槽是基于广播通信体系设计出来的,它采用无连接的不可靠的数据传输。邮槽是一种单向通信机
制,创建邮槽的服务器进程读取数据,打开邮槽的客户机进程写入数据。为保证邮槽在各种Windows
平台下都能够正常工作,我们在传输消息的时候,应将消息的长度限制在424字节以下。
在程序中,可以通过调用 CreateMailslot函数创建一个邮槽。该函数利用指定的名称创建一个邮槽,
然后返回所创建的邮槽的句柄。 CreateMailslot函数的原型声明如下所示:
HANDLE CreateMailslot(
LPCTSTR lpName ,
DWORD nMaxMessageSìze,
DWORD lReadTimeout ,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
CreateMailslot函数有四个参数,其含义分别如下所示。
. IpName
指向一个空终止字符串的指针,该字符串指定了邮槽的名称,该名称的格式必须是: "\.\mailslo
叭[path]name",其中前两个反斜杠之后的字符表示服务器所在机器的名称,圆点表示是本地主机:
接着是硬编码的字符串: "mailslot",这几个字符不能改变,但大小写无所谓:最后的字符串
( [path]name)就是程序员为邮槽取的名称。
nM~essageSize
用来指定可以被写入到邮槽的单一消息的最大尺寸,为了可以发送任意大小的消息,
可以将该参数设置为0。
. lReadTimeout
指定读取操作的超时时间间隔,以m为单位。读取操作在超时之前可以等待一个消息被写入到这个邮
槽之中。如果将这个值设置为 0,那么若没有消息可用,该函数将立即
返回:如果将这个值设置为 MAILSLOT_WAIT_FORE\rER.则该函数将一直等待,直到有消息可用。
. lpSecurityAttributes
指向一个 SECURITY_ATI'RIBUTES结构的指针。可以简单地给这个参数传递 NULL值,让系统为所创
建的邮槽赋予默认的安全描述符。
17.4.1 服务器端程序
下面就利用邮槽实现进程间的通信,首先实现服务器程序。新建一个单文档类型的 MFC应用程序,
工程取名为: MailslotSrv。因为对邮槽服务器端进程来说,它只能接收数据,所以为该工程添加一
个子菜单,并在其属性对话框中取消 Pop-up选项,使其成为一个可响应的菜单项,将其名称设置为:
接收数据, ID设置为: IDM_MAil_sLOT_RECV。然后为该菜单项添加命令响应函数,并选择
CMailslotSrvView类作为响应类。接下来,就可以在此响应函数中实现邮槽服务器端程序的功能,
结果代码如例 17-15所示。
例 17-15
void CMailslotSrvView::OnMailslotRecv()
// TODO: Add your command handler code here
HANDLE hMailslot;
//创建邮槽
hMailslot=CreateMailslot("\\\\.\\mailslot\\MyMailslot" , 0,
MAILSLOT_WAIT_FOREVER, NULL);
if(INVALID_HANDLE_VALUE== hMailslot)
MessageBox("创建邮槽失败!");
return;
char buf[100];
DWORD dwRead;
//从邮槽读取数据
if(!ReadFile(hMailslot , buf , 100, &dwRead, NULL) )
MessageBox("读取数据失败!");
CloseHandle(hMailslot);
return;
MessageBox(buf) ;
CloseHandle(hMailslot) ;
在如例 17-15所示代码中,首先定义了一个句柄变量: hMailslot.用来保存将要创建的邮槽的句柄。
然后调用 CreateMailslot函数创建一个邮槽。在调用这个函数时,将邮槽名称指定为: MyMailslot;
第二个参数设置为 O.让消息可以是任意大小:把第三个参数,即读取超时间隔设置为
MAILSLOT_WAIT_FOREVER.让函数一直等待:最后一个参数设
置为 NULL,让系统为所创建的邮槽赋予默认的安全描述符。
如果 CreateMailslot函数调用失败,函数将返回 INVALID-HANDLE-VALUE值,因此在程序中如果判
断该函数返回的是因VALID_HANDLE_VALUE,则提示用户 z咄建邮槽失败!",井立即返回。
因为对邮槽服务器端进程来说,它只能接收数据,所以如果邮槽创建成功,那么就可以直接调用
ReadFile函数从邮槽读取数据了,并显示读取到的数据。
最后,调用 CloseHandle函数关闭邮槽句柄。
以上就是邮槽服务器端程序的实现,利用 Build命令生成 MailslotS凹程序。
17.4.2 客户端程序
同样,我们可以将邮槽客户端工程增加到己有的 MailslotSrv工作区中,在此工作区中新建一个单
文档类型的 MFC应用程序,工程取名为: MailslotClt,同时设置该工程所在的目录与 MailslotSrv
工程的目录平级。
因为对邮槽客户端程序来说,只能是发送数据。所以,同样为客户端程序增加一个子菜单,并在其
属性对话框中取消 Pop-up选工页,使其成为一个可响应的菜单项,将名称设置为:发送数据, ID
设置为: IDM_MAILSLOT_SEND。然后为该菜单项添加命令响应函数,并选择 CMailslotCltView类作
为响应类。接下来,就可以在此响应函数中实现邮槽客户端程序的功能,结果代码如例 17-16所示。
例 17-16
void CMailslotCltView::OnMailslotSend()
{ 11 TODO: Add your cornmand handler code here
HANDLE hMailslot;
11打开邮槽
hMailslot=CreateFile("\\\\.\\mailslot\\MyMailslot" , GENERIC_WRITE ,
FILE_SHARE_READ, FILE_ATTRIBUTE_NORMAL
if(工 NVALID_HANDLE_VALUE== hMailslot) NULL , ,
OPEN_EX工 STING, NULL);
MessageBox("打开邮槽失败!"); return;
char buf[l=''http://www.sunxin.org"; DWORD dwWrite; 11向邮槽写入数据
if(!WriteFile(hMailslot, buf, strlen(buf)+l , &dwWrite , NULL))
MessageBox("写入数据失败!");
CloseHandle(hMailslot) ;
return;
CloseHandle(hMailslot);
在如例 17-16所示代码中,首先定义了一个句柄变量=hMailslot,用来保存随后打开的邮槽句柄。
对于邮槽客户端来说,它首先需要打开邮槽,同样的,这也是通过调用 CreateFile函数实现的,该
函数的第一个参数指定邮槽的名称:第二个参数指定访问万式,对客户端程序来说,只能是写入数据,
所以使用GENANRC_WRITE;第三个参数是共享的方式,对邮槽客户端来说,它只能是写入数据,由服务
器端读取数据,所以这里需要设置一个共享读 (FILE_SHARE_READ)标志,让服务器端进程可以从邮
槽读取数据:第四个参数指定安全描述符,本例将其设置为NULL,即使用系统默认的安全性:第五个
参数指定打开的方式,本例将其设置为OPEN-EXISTING标志;第六个参数指定文件属性,本例将其指
定为FILE_.π阳BU四,_NORMAL;最后一个参数指定模板文件,本例将其设置为
NULL。
接着,上述程序判断CreateFile函数的返回值,如果该函数调用失败,将返回的VALID HANDLE_VALUE
值,这时就提示用户:"打开邮槽失败!"。因为对客户端程序来说,如果邮槽打开操作成功,就可以
向邮槽发送数据了,这可以通过调用WriteFile函数实现。
在数据写入操作完成之后,应该调用CloseHandle关闭邮槽句柄。
以上就是邮槽客户端程序的实现,利用Build命令生成MailslotClt程序。
到此为止,我们就完成了利用邮槽实现进程间通信的服务端程序和客户端程序,读者
可以看到,这两个程序的编写都比较简单。首先,服务器端需要调用 CreateMailslot函数创建邮槽,
要注意的是,如果邮件服务端进程和客户端进程不在同一台机器上运行,那么, 本例中指定的邮槽
名称字符串中的圆点应该替换为服务器进程运行所在的机器的主机名。之后,如果邮槽创建成功,
就可以调用ReadFile函数从邮槽读取数据了。而邮槽的客户端首先应该调用 CreateFile函数打开指
定的邮槽,如果打开操作成功,就可以调用 WriteFile函数向邮槽写入数据了。
我们可以分别运行上述实现的MailslotSrv和MailslotClt程序。然后,单击服务器端的【接收数据】
菜单项,接着单击客户端的【发送数据】菜单项,即可看到邮槽服务器端接收到数据了,程序运行
界面如图 17.8所示。
图 17.8利用邮槽实现进程间通信的程序运行结果
读者可能会有这样的疑问,邮槽只能实现单向通信,那么如果想利用邮槽编写一个既能读取数据,
又能发送数据的程序时应该怎么办呢?其实解决方法很简单,我们只需要在
同一个程序中同时实现邮槽的服务器端(即读取端)和客户端(即发送端),利用前者接
收数据,利用后者发送数据即可。这样,就可以在同一个程序中通过邮槽接收和发送数据了。
另外,邮槽是基于广播通信的,也就是说,邮槽可以实现一对多的单向通信,我们可以利用邮槽这
一特性编写一个网络会议通知系统,而且实现这样的系统所需编写的代码非常少。如果读者是一位
项目经理,就可以给你手下每一位员工的机器上安装上这个系统中的邮槽服务器端程序,在你自己
的机器上安装邮槽的客户端程序。这样,当你想要通知员工开会,就可以通过己安装的邮槽客户端
程序将开会通知这一信息发送出去,因为员工机器上都安装了邮槽服务器端程序,所以他们都能同
时接收到你发出的会议通知信息。采用邮槽实现这样的程序是非常简单的,如果采用 Sockets来实
现这样的通信,代码将比较复杂。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -