邮槽

科技工作者之家 2020-11-17

邮槽是Windows操作系统提供的一种单向进程间通信机制,可用于单机或者网络上的多机分布式环境。对于相对简短的低频率信息发送,使用邮槽通常比命名管道或Unix域套接字更简单。如低频率的状态改变消息、作为对等点发现协议(peer-discovery protocol)的一部分。 邮槽机制允许短报文广播给域上的计算机中所有监听的进程。

简介邮槽采用的是一种比较简单的客户/服务器体系。创建并拥有邮槽的进程为服务器,不管该进程是在主域服务器上还是在由Windows9X与NTWorkstation组成的工作站上都被视为邮槽服务器。邮槽服务器可以设置、修改邮槽的属性,并读取邮槽中的数据。而向指定的邮槽写入消息的进程则为邮槽客户,同样它不考虑邮槽所处机器在网络上的具体身份。邮槽客户在获得邮槽句柄之后,调用Writefile()函数将数据写入邮槽,写入邮槽的数据将加入到队列中,也就是说邮槽客户可以向服务器发送任何形式的数据,但服务器不能向客户发送数据。邮槽工作方式有三大特点:

①单向通讯:创建邮槽的服务器只能读取消息,不能写入消息,而客户端则与之刚好相反。如果某一端应用程序要同时具备读取与写入的双向功能,那么必须在两端的应用程序分别建立两个邮槽;②广播消息。假如在域上有若干计算机使用同样的名称创建邮槽,那么某一邮槽客户可以一次性向所有的同名邮槽服务器发送消息;③数据报传输。邮槽对消息的传输为数据报方式,即客户端只负责数据的发送,而服务器端并不回应客户端发送的数据是否接收到。

邮槽是一种服务器-客户接口。服务器创建邮槽,客户可以向命名的邮槽写入内容。只有服务器可以读取邮槽,因此邮槽是一种单向进程间通信机制。邮槽不提供报文已收到的确认,因此是不可靠通信。

邮槽基于RPC协议,可以在同一个网络域上跨计算机使用。1

应用Windows信使服务是邮槽的最知名的应用。信使服务是一个邮槽服务器,等待报文到达后,就弹窗显示在屏幕上。

邮槽的应用举例:

MAILSLOT\Messngr - 微软NET SEND协议

MAILSLOT\Browse - 微软网络邻居共享资源浏览服务

MAILSLOT\Alerter

MAILSLOT\53cb31a0\UnimodemNotifyTSP

MAILSLOT\HydraLsServer - Microsoft Terminal Services Licensing

MAILSLOT\CheyenneDS -CABrightStor Discovery Service

实现邮槽命名邮槽的名字,从形式上看类似于文件名。格式为“\\ComputerName\mailslot\[path]name”本地邮槽名字中的ComputerName使用.来代替,即“\\.\MailSlot\路径\文件名”。如果向当前发送计算机所在工作组或域群发,可以使用“*”作为ComputerName。如果向指定工作组或域群发,应使用工作组或域名作为ComputerName。本机的Windows的信使服务使用的邮槽名字是”\\.\MailSlot\ messngr“。

邮槽报文内容邮槽报文内容包含:接收日期、发送人、接收人、具体内容。发送人、接收人、具体内容三项内容之间使用字节值0间隔。

创建邮槽使用“CreateMailslot”创建邮槽。

写入报文到邮槽类似于写入普通文件,使用“CreateFile”打开邮槽,使用“WriteFile”将内容写入。也可以使用“NetMessageBufferSend”直接发送。

读取邮槽报文使用“GetMailSlotInfo”来判断邮槽内是否有内容。发现有内容的时候,可以使用“ReadFile”读取。如果“ReadFile”在使用MAILSLOT_WAIT_FOREVER标志的邮槽上等待消息到来,这时邮槽突然中止运行,那么这个应用会被永远“挂起”直至重启Windows系统。为此,读邮槽的进程可以使用一个单独线程执行读挂起操作;主线程要结束进程时给一个全局标志位置位,并给邮槽写入一条消息以唤醒读邮槽线程。“SetMailslotInfo”设置读取邮槽的超时值。

例子:

//邮槽服务器,负责创建邮槽,读取邮槽#include #include int main(){ HANDLE Mailslot; char buffer[256]; DWORD NumberOfBytesRead; //Create the mailslot Mailslot = CreateMailslot("////.//Mailslot//Myslot", //指定邮槽的名字 0, //可写入邮槽的消息的最大字节长度;为0表示接收任意长度消息 MAILSLOT_WAIT_FOREVER, //等待或不等待,单位毫秒,MAILSLOT_WAIT_FOREVER无限期等待,0立即返回 NULL); //访问控制权限,一般为NULL if (INVALID_HANDLE_VALUE == Mailslot) { printf("Failed to create a mailslot %d/n", GetLastError()); return -1; } //Read data from the mailslot forever! while (0 != ReadFile(Mailslot, buffer, 256, &NumberOfBytesRead, NULL)) { printf("%.*s/n",NumberOfBytesRead,buffer); } CloseHandle(Mailslot); return 0;}//邮槽客户端,用于发送数据到邮槽服务器#include #include int main(int argc, char *argv[]){ HANDLE Mailslot; DWORD BytesWritten; CHAR ServerName[256]; //从命令行接受要发送数据到的服务器名 if (argc

科技工作者之家

科技工作者之家APP是专注科技人才,知识分享与人才交流的服务平台。