27-进程间通信:邮槽

进程间通信:邮槽

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

邮槽通信是单向的,只有服务端才能从邮槽中读取消息,客户端只能写入消息。消息是先入先出的。客户端先写入的消息在服务端先被读取。通过邮槽通信的数据可以是任意格式的,但是一条消息不能大于 424 字节。

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

1.服务端创建邮槽的函数CreateMailslot

LPCTSTR szSlotName = TEXT("\\\\.\\mailslot\\Mymailslot");
HANDLE hSlot = CreateMailslot(
szSlotName,
0, // no maximum message size
MAILSLOT_WAIT_FOREVER, // no time-out for operations
NULL
);

2.客户端获取邮槽的函数CreateFile

根据约定好的邮槽名,将邮槽作为一个文件打开

LPCTSTR szSlotName = TEXT("\\\\.\\mailslot\\Mymailslot");
HANDLE hMailSlot =
CreateFile(szSlotName, FILE_GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL );

3.案例

服务端

void CChildView::OnSlot()
{
// "\\\\.\\mailslot\\Mymailslot \\.\mailslot\Mymailslot
// 1 创建一个邮槽
LPCTSTR szSlotName = TEXT("\\\\.\\mailslot\\Mymailslot");
HANDLE hSlot = CreateMailslot(szSlotName,
0, // no maximum message size
MAILSLOT_WAIT_FOREVER, // no time-out for operations
NULL); // default security
if (hSlot == INVALID_HANDLE_VALUE)
{
TRACE("CreateMailslot failed with %d\n", GetLastError());
return ;
}
// 2 读取数据
char szBuf[100] = { 0 };
DWORD dwRead;
TRACE("Begin ReadFile");
if (!ReadFile(hSlot, szBuf, 100, &dwRead, NULL)) //阻塞直到邮槽中有数据
{
MessageBox(_T("读取数据失败"));
CloseHandle(hSlot);
return;
}
TRACE("End ReadFile");
MessageBox((CStringW)szBuf);
CloseHandle(hSlot);
}

客户端

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[] = "Bingo is handsome";
DWORD dwWrite;
if (!WriteFile(hMailSlot, szBuf, strlen(szBuf) + 1, &dwWrite, NULL))
{
MessageBox(_T("写入数据失败"));
CloseHandle(hMailSlot);
return;
}
CloseHandle(hMailSlot);
}