邮槽是基于广播通信体系设计出来的,它采用无连接的不可靠UDP数据传输协议。使用邮槽通信的进程分为客户端和服务端,邮槽由服务端创建,创建后,客户端可以通过邮槽名打开邮槽,在获得邮槽句柄后可以向邮槽写入消息。邮槽通信是单向的,只有服务端能从邮槽中读取消息,而客户端只能写入消息。消息是先进先出的。
通过邮槽通信的数据可以是任意格式的,但为了保证邮槽在各种Windows平台下都能够正常工作,邮槽通信一条消息的长度不能大于424字节。邮槽除了在本机上进行进程间通信外,还可以在主机之间进行通信。
实际上一个邮槽是驻留在内存中的一个Windows临时虚拟文件,利用Windows标准文件函数可以对邮槽写入或读取消息,但它不同于磁盘文件的地方是:当邮槽句柄被关闭后,邮槽中的消息将被全部删除。
因此,邮槽工作方式有三大特定:1)单向通信;2)广播消息;3)数据报传输。
1)邮槽的命名:
本机上邮槽命名格式://./mailslot/[path/]name;
例如://./mailslot/win/asce_comment;
不同主机间命名格式://DomainName/mailslot/[path/]name;
//ComputerName/mailslot/[path/]name;
也可以使用通配符,以进行广播://*/mailslot/[path/]name;
格式的说明:前两个反斜杠之后的字符表示服务器所在机器的名称,圆点表示是本地主机;“mailslot”是硬编码的,这几个字符不能改变,但大小写无所谓。“[path/]name”当然就是邮槽名字了。
2)关键的API
CreateMailslot,创建一个邮槽对象:
HANDLE WINAPI CreateMailslot(
__inLPCTSTR lpName,//邮槽名
__inDWORD nMaxMessageSize,//单一消息最大长度,为了可以发送任意大小的消息,
//一般将该参数设置为0
__inDWORD lReadTimeout,//读超时的时间:0(如果没有消息时立即返回);
//MAILSLOT_WAIT_FOREVER(直到读到消息才返回)
__in_optLPSECURITY_ATTRIBUTES lpSecurityAttributes//安全属性
);
例子如下:
#include<windows.h>
#include<stdio.h>
HANDLE hSlot;
LPTSTR Slot = TEXT("////.//mailslot//sample_mailslot");
BOOL WINAPI MakeSlot(LPTSTR lpszSlotName)
{
hSlot = CreateMailslot(lpszSlotName,
0,// no maximum message size
MAILSLOT_WAIT_FOREVER,// no time-out for operations
(LPSECURITY_ATTRIBUTES) NULL);// default security
if(hSlot == INVALID_HANDLE_VALUE)
{
printf("CreateMailslot failed with %d/n", GetLastError());
returnFALSE;
}
elseprintf("Mailslot created successfully./n");
returnTRUE;
}
voidmain()
{
MakeSlot(Slot);
}
GetMailslotInfo,获取指定邮槽的相关信息:
BOOL WINAPI GetMailslotInfo(
__inHANDLE hMailslot,//邮槽的句柄
__out_optLPDWORD lpMaxMessageSize,//返回消息的最大长度
__out_optLPDWORD lpNextSize,//返回下一条消息的长度
__out_optLPDWORD lpMessageCount,//返回消息的数量
__out_optLPDWORD lpReadTimeout//返回读超时时间
);
例子如下:(这个例子同时是一个完整的邮槽服务端)
#include<windows.h>
#include<tchar.h>
#include<stdio.h>
#include<strsafe.h>
HANDLE hSlot;
LPTSTR SlotName = TEXT("////.//mailslot//sample_mailslot");
BOOL ReadSlot()
{
DWORD cbMessage, cMessage, cbRead;
BOOL fResult;
LPTSTR lpszBuffer;
TCHAR achID[80];
DWORD cAllMessages;
HANDLE hEvent;
OVERLAPPED ov;
cbMessage = cMessage = cbRead = 0;
hEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("ExampleSlot"));
if( NULL == hEvent )
returnFALSE;
ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = hEvent;
fResult = GetMailslotInfo( hSlot,// mailslot handle
(LPDWORD) NULL,// no maximum message size
&cbMessage,// size of next message
&cMessage,// number of messages
(LPDWORD) NULL);// no read time-out
if(!fResult)
{
printf("GetMailslotInfo failed with %d./n", GetLastError());
returnFALSE;
}
if(cbMessage == MAILSLOT_NO_MESSAGE)
{
printf("Waiting for a message.../n");
returnTRUE;
}
cAllMessages = cMessage;
while(cMessage != 0)// retrieve all messages
{
// Create a message-number string.
StringCchPrintf((LPTSTR) achID,
80,
TEXT("/nMessage #%d of %d/n"),
cAllMessages - cMessage + 1,
cAllMessages);
// Allocate memory for the message.
lpszBuffer = (LPTSTR) GlobalAlloc(GPTR,
lstrlen((LPTSTR) achID)*sizeof(TCHAR) + cbMessage);
if( NULL == lpszBuffer )
returnFALSE;
lpszBuffer[0] ='/0';
fResult = ReadFile(hSlot,
lpszBuffer,
cbMessage,
&cbRead,
&ov);
if(!fResult)
{
printf("ReadFile failed with %d./n", GetLastError());
GlobalFree((HGLOBAL) lpszBuffer);
returnFALSE;
}
// Concatenate the message and the message-number string.
StringCbCat(lpszBuffer,
lstrlen((LPTSTR) achID)*sizeof(TCHAR)+cbMessage,
(LPTSTR) achID);
// Display the message.
_tprintf(TEXT("Contents of the mailslot: %s/n"), lpszBuffer);
GlobalFree((HGLOBAL) lpszBuffer);
fResult = GetMailslotInfo(hSlot,// mailslot handle
(LPDWORD) NULL,// no maximum message size
&cbMessage,// size of next message
&cMessage,// number of messages
(LPDWORD) NULL);// no read time-out
if(!fResult)
{
printf("GetMailslotInfo failed (%d)/n", GetLastError());
returnFALSE;
}
}
CloseHandle(hEvent);
returnTRUE;
}
BOOL WINAPI MakeSlot(LPTSTR lpszSlotName)
{
hSlot = CreateMailslot(lpszSlotName,
0,// no maximum message size
MAILSLOT_WAIT_FOREVER,// no time-out for operations
(LPSECURITY_ATTRIBUTES) NULL);// default security
if(hSlot == INVALID_HANDLE_VALUE)
{
printf("CreateMailslot failed with %d/n", GetLastError());
returnFALSE;
}
returnTRUE;
}
voidmain()
{
MakeSlot(SlotName);
while(TRUE)
{
ReadSlot();
Sleep(3000);
}
}
SetMailslotInfo,修改已创建邮槽读操作的超时时间:
BOOL WINAPI SetMailslotInfo(
__inHANDLE hMailslot,//邮槽句柄
__inDWORD lReadTimeout//新的读超时时间
);
邮槽的客户端代码如下:
#include<windows.h>
#include<stdio.h>
LPTSTR SlotName = TEXT("////.//mailslot//sample_mailslot");
BOOL WriteSlot(HANDLE hSlot, LPTSTR lpszMessage)
{
BOOL fResult;
DWORD cbWritten;
fResult = WriteFile(hSlot,
lpszMessage,
(DWORD) (lstrlen(lpszMessage)+1)*sizeof(TCHAR),
&cbWritten,
(LPOVERLAPPED) NULL);
if(!fResult)
{
printf("WriteFile failed with %d./n", GetLastError());
returnFALSE;
}
printf("Slot written to successfully./n");
returnTRUE;
}
intmain()
{
HANDLE hFile;
hFile = CreateFile(SlotName,
GENERIC_WRITE,
FILE_SHARE_READ,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
printf("CreateFile failed with %d./n", GetLastError());
returnFALSE;
}
WriteSlot(hFile, TEXT("Message one for mailslot."));
WriteSlot(hFile, TEXT("Message two for mailslot."));
Sleep(5000);
WriteSlot(hFile, TEXT("Message three for mailslot."));
CloseHandle(hFile);
returnTRUE;
}
由于邮槽是基于广播通信的,所以邮槽可以实现一对多的单向通信,例如,我们可以利用邮槽编写一个网络会议的通知系统。在每个被通知人电脑上安装服务端,通知人电脑上安装客户端即可。
分享到:
相关推荐
2.3 Windows API核心DLL 21 2.3.1 Kernel32.dll 21 2.3.2 User32.dll 21 2.3.3 Gdi32.dll 22 2.3.4 标准C函数 22 2.3.5 其他Dll 22 2.4 Unicode和多字节 22 2.4.1 W版本和A版本的API 24 2.4.2 ...
4.3.2 邮槽服务器端与客户端之间通信的实例 86 4.4 如何用Windows套接字进行进程间通信 90 4.4.1 套接字分类 90 4.4.2 流式套接字编程流程 91 4.4.3 套接字调用基本函数 92 4.4.4 Winsock程序设计 95 4.4.5 一...
2.3 Windows API核心DLL 21 2.3.1 Kernel32.dll 21 2.3.2 User32.dll 21 2.3.3 Gdi32.dll 22 2.3.4 标准C函数 22 2.3.5 其他Dll 22 2.4 Unicode和多字节 22 2.4.1 W版本和A版本的API 24 2.4.2 ...
这种松耦合的通信方式简化了异步编程和事件处理。 QML与Qt Quick: QML是一种声明性语言,结合JavaScript,用于快速创建流畅、动态的用户界面。它与Qt Quick框架紧密集成,特别适合开发现代化、触屏友好的应用。 ...
信号和槽机制是 QT 的核心机制,要精通 QT 编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方。 在linux、windows等 GUI 工具...
Qt的元对象系统(Meta-Object-System)提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统。 元对象系统由以下三个基础组成: 1.QObject类是所有使用元对象系统的类的基类; 2.在一个类的private部分...
Qt的元对象系统(Meta-Object-System)提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统。 元对象系统由以下三个基础组成: 1.QObject类是所有使用元对象系统的类的基类; 2.在一个类的private部分...
这种松耦合的通信方式简化了异步编程和事件处理。 QML与Qt Quick: QML是一种声明性语言,结合JavaScript,用于快速创建流畅、动态的用户界面。它与Qt Quick框架紧密集成,特别适合开发现代化、触屏友好的应用。 ...
这种松耦合的通信方式简化了异步编程和事件处理。 QML与Qt Quick: QML是一种声明性语言,结合JavaScript,用于快速创建流畅、动态的用户界面。它与Qt Quick框架紧密集成,特别适合开发现代化、触屏友好的应用。 ...
这种松耦合的通信方式简化了异步编程和事件处理。 QML与Qt Quick: QML是一种声明性语言,结合JavaScript,用于快速创建流畅、动态的用户界面。它与Qt Quick框架紧密集成,特别适合开发现代化、触屏友好的应用。 ...
这种松耦合的通信方式简化了异步编程和事件处理。 QML与Qt Quick: QML是一种声明性语言,结合JavaScript,用于快速创建流畅、动态的用户界面。它与Qt Quick框架紧密集成,特别适合开发现代化、触屏友好的应用。 ...