`
isiqi
  • 浏览: 16590635 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

进程间通信之邮槽

阅读更多

简介

有时候我们需要一个程序与另一个程序之间进行通信。你可能在多台机器上有多个服务器运行,而在一个中央位置对一个或多个服务器进行远程监控。 Windows 平台为我们提供了一系列通信方式,从 Socket 到命名管道, DDE,DCOM ,邮槽等。本文中作者将探讨邮槽这一通信机制,假定读者熟悉 CreateFile(),ReadFile(),WriteFile() API 函数,此外还假定读者熟悉重叠 I/O 的基础知识。

邮槽

实现一个 多写者 / 单读者 协议。一个进程通过指定一个名称创建一个邮槽,然后等待有消息写入到邮槽中。若其他进程知道邮槽的名称,则可以打开邮槽,往邮槽中写入消息。只能有一个邮槽读者,但可以有多个写者。微软使用服务器 / 客户来描述。服务器创建邮槽并从中读取消息。客户连接到一个已经存在的邮槽,并往里面写入消息。

邮槽有一个有趣而有用的属性。一个进程往邮槽中写入一个消息,读者就可以接收到消息。消息是一整块任意长度的数据,若写者写入 60 字节,读者读到 60 字节,不多不少。若写者写 327 字节,读者读到 327 字节。这是一个面向消息的协议,而不是面向字节的协议。这类似于命名管道上的消息模式。这并不是说你不能只读取消息的一部分,只不过使用邮槽的 自然 方式是面向消息的,这在对读者可用的 API 里反映出来。

邮槽可以跨网络使用。若在同一台机器上,则你可以给邮槽命名为 ""."mailslot"slotname 。若跨网络使用,则你可以将 ”.” 替换为创建邮槽的机器的名称。

创建邮槽

这通过 CreateMailslot() 函数完成,第一个参数指明了邮槽名称。其他参数依次是能写入邮槽中的消息的最大大小,邮槽读者等待消息的时间,一个指明句柄是否被子进程继承的安全描述符。

连接邮槽

你可以使用 CreateFile() 函数,在其中指定邮槽名称来实现。若你希望实现多写者 / 单读者模式,你必须在打开邮槽时小心共享模式。若邮槽写者打开邮槽时没有指定 FILE_SHARE_WRITE 为共享模式,那么它将阻止其他任何写者往邮槽里写入消息。

邮槽的句柄,何以处之?

若你通过 CreateMailslot() 函数创建邮槽,你可以使用 ReadFile() 从中读取消息。邮槽句柄在重叠 I/O 模式中创建,因此你可以在它上面使用重叠 I/O ,当然若合适的话,你也可以使用非重叠 I/O 模式。你可以调用 GetMailslotInfo() 函数来查询有等待被读取的消息的个数,下一个消息的长度,读取消息的超时时限。你可以调用 SetMailslotInfo() 函数来改变超时时限。注意你传递给这两个函数的句柄必须是通过 CreateMailslot() 创建的。

若你没有创建邮槽,然后你使用 CreateFile() 函数连接到邮槽上。这种情况下你可以使用 WriteFile() 函数往邮槽里写入消息。你能否使用重叠 I/O 模式取决于你如何调用 CreateFile() 函数的方式。它可以是同步的,也可以是异步的。你无法使用 CreateFile() 函数连接到一个邮槽上并且从邮槽上读取消息。

MSDN 关于的邮槽的文档说只要邮槽上有任何一个打开句柄,邮槽就会存在。但作者说这不一定正确(在 win xp sp2 上)。 你可以有任何数量的打开的邮槽写句柄,但只要读者句柄一关闭,邮槽就消失了(一旦读句柄关闭,往邮槽中写入消息就会失败)。这是有意义的。因为你只有一个 读者,它一旦走了,那么任何写入的消息都只会被系统无意义地缓存。若没有读者了,那么缓存的消息就会永远悬停了(记住你无法使用 CreateFile() 来打开邮槽的读句柄)。

可以连接到特定域的特定名字的所有邮槽。这通过指定邮槽名称为 “""domainname"mailslot"name“ 。也可以使用 ”*” 作为首要域。这看起来不错,你可以在一个域内运行的多台机器上的任何数量的读者,并且指定域名同时往邮槽中写入消息。但有个问题,若你使用域名作为邮槽的写者,你没法写入大于 424 字节的消息。

BOOLMakeslot()
{ // 创建邮槽
CStringlpszSlotName = _T( " \\\\.\\mailslot\\sample_mailslot " );
// Themailslothandle"hSlot1"isdeclaredglobally.
hSlot1 = CreateMailslot(lpszSlotName.GetBuffer( 10 ),
0 , // nomaximummessagesize
MAILSLOT_WAIT_FOREVER, // notime-outforoperations
(LPSECURITY_ATTRIBUTES)NULL); // nosecurityattributes
if (hSlot1 == INVALID_HANDLE_VALUE)
{
return FALSE;
}

return TRUE;
}
BOOLReadslot()
{ // 读邮槽
DWORDcbMessage,cMessage,cbRead;
BOOLfResult;
LPWSTRlpszBuffer;
TCHARachID[
80 ];
DWORDcAllMessages;
HANDLEhEvent;
OVERLAPPEDov;
cbMessage
= cMessage = cbRead = 0 ;
hEvent
= CreateEvent(NULL,FALSE,FALSE,_T( " ExampleSlot " ));
ov.Offset
= 0 ;
ov.OffsetHigh
= 0 ;
ov.hEvent
= hEvent;
// Mailslothandle"hSlot1"isdeclaredglobally.
fResult = GetMailslotInfo(hSlot1, // mailslothandle
(LPDWORD)NULL, // nomaximummessagesize
& cbMessage, // sizeofnextmessage
& cMessage, // numberofmessages
(LPDWORD)NULL); // noreadtime-out
if ( ! fResult)
{
// ErrorHandler(hwnd,"GetMailslotInfo");
return FALSE;
}

if (cbMessage == MAILSLOT_NO_MESSAGE)
{
// TextOut(hdc,10,10,"Nowaitingmessages.",20);
return TRUE;
}

cAllMessages
= cMessage;
while (cMessage != 0 ) // retrieveallmessages
{
// Createamessage-numberstring.
wsprintf((LPWSTR)achID,
_T(
" \nMessage#%dof%d\n " ),cAllMessages - cMessage + 1 ,
cAllMessages);
// Allocatememoryforthemessage.
lpszBuffer = (LPWSTR)GlobalAlloc(GPTR,
lstrlen((LPWSTR)achID)
+ cbMessage);
lpszBuffer[
0 ] = ' \0 ' ;
fResult
= ReadFile(hSlot1,
lpszBuffer,
cbMessage,
& cbRead,
& ov);
if ( ! fResult)
{
// ErrorHandler(hwnd,"ReadFile");
GlobalFree((HGLOBAL)lpszBuffer);
return FALSE;
}

// Concatenatethemessageandthemessage-numberstring.
lstrcat(lpszBuffer,(LPWSTR)achID);
GlobalFree((HGLOBAL)lpszBuffer);

fResult
= GetMailslotInfo(hSlot1, // mailslothandle
(LPDWORD)NULL, // nomaximummessagesize
& cbMessage, // sizeofnextmessage
& cMessage, // numberofmessages
(LPDWORD)NULL); // noreadtime-out

if ( ! fResult)
{
return FALSE;
}

}

return TRUE;
}

BOOLWriteslot()
{ // 写邮槽
CStringlpszMessage = _T( " Messageforsample_mailslotinprimarydomain. " );
BOOLfResult;
HANDLEhFile;
DWORDcbWritten;

hFile
= CreateFile(_T( " \\\\.\\mailslot\\sample_mailslot " ),
GENERIC_WRITE,
FILE_SHARE_READ,
// requiredtowritetoamailslot
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE)NULL);

if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}


fResult
= WriteFile(hFile,
lpszMessage.GetBuffer(
10 ),
(DWORD)lstrlen(lpszMessage)
+ 1 , // includeterminatingnull
& cbWritten,
(LPOVERLAPPED)NULL);

if ( ! fResult)
{
return FALSE;
}

fResult
= CloseHandle(hFile);

if ( ! fResult)
{
return FALSE;
}

return TRUE;

}

作者:洞庭散人

分享到:
评论

相关推荐

    C++ MFC 进程间通信之邮槽

    综上所述,C++ MFC的邮槽通信是一种有效的进程间通信手段,通过消息队列和消息映射机制,开发者可以方便地在不同进程之间传递数据。理解并熟练掌握这一技术,对于开发复杂的多进程应用具有重要意义。在实际项目中,...

    进程间通信-邮槽,邮槽,邮槽

    通过深入理解邮槽的工作原理及其在进程间通信中的应用,开发者能够有效地设计和实现高效的多进程协同工作系统,提高软件的性能和可靠性。在实际编程中,根据项目需求选择合适的邮槽实现方式,并注意处理好同步、错误...

    进程间通信之邮槽demo

    通过mailsolt来实现进程间通信,使用方法: 两个exe,一个服务端一个客户端,打开服务端创建邮槽 再打开客户端输入要发送的信息点击发送 回到服务端点击接受,注意每次发送信息前都需要创建邮槽。

    进程间通信-邮槽

    在实际应用中,选择邮槽作为进程间通信方式时,需要根据项目需求来评估其适用性。如果需要高效、简单的通信,且消息较小,邮槽是不错的选择。如果需要更复杂的数据共享和同步机制,或者大消息传输,可能需要考虑其他...

    进程间通过邮槽通信实例

    邮槽(Mailslot)是Windows操作系统提供的一种进程间通信(IPC, Inter-Process Communication)机制,主要用于在同一台计算机或网络中的不同进程之间传递消息。在本实例中,我们使用Visual Studio 2010作为开发环境...

    进程通信--邮槽

    邮槽(Message Queue)是一种典型的进程间通信(IPC,Inter-Process Communication)机制,尤其在多任务环境中的应用十分广泛。邮槽通信方式在Windows系统中尤为常见,它提供了一种有序、非阻塞的消息传递机制。 邮...

    进程间通信的VC++源码实例集,邮槽、匿名管道等

    进程间通信的VC++源码实例集,进程之间的通信以及实现方法实例,通过一些小程序来实现,这些小程序有剪贴板实例、邮槽、匿名管道等,希望对VC++基础用户有帮助。

    进程间通信源码

    在Windows系统中,VC++编程语言提供了多种实现进程间通信的方法,其中包括邮槽(Message Queues)、匿名管道(Anonymous Pipes)等。本源码实例集将深入探讨这些方法,并提供实际的代码示例。 首先,我们来看邮槽...

    VC++ 四种进程间通信的完整实例

    VC++ 四种进程间通信的完整实例,一般来说,进程通信采取四种形式:剪贴板、匿名管道、命名管道、邮槽。孙鑫将带你用实例来验证这四种方式的优略性,进而帮助VC编程者熟悉掌握进程间通信的方方面面,并附有孙鑫老师...

    11进程间通讯_邮槽

    邮槽(Mailslot)是Windows操作系统提供的一种简单、轻量级的进程间通信方式,尤其适用于服务器与客户端之间的消息传递。在这个主题中,我们将深入探讨邮槽的原理、使用方法以及在VC++环境下如何实现。 邮槽是一种...

    c++ 进程间通信

    在C++编程中,实现进程间通信有多种方法,其中包括剪贴板、匿名管道、命名管道和邮槽。接下来,我们将详细探讨这四种方式。 1. **剪贴板**: 剪贴板是一种共享内存的方式,它允许进程将数据复制到剪贴板后,其他...

    一个简单的邮槽例子,包含客户端和服务器

    邮槽(MailSlot)是Windows操作系统提供的一种进程间通信(IPC, Inter-Process Communication)机制,主要用于在同一台计算机上的不同进程之间传递数据。这个简单的邮槽例子包括了客户端(MailSlotClient)和服务器...

    邮槽服务器端和邮槽客户端

    邮槽(Mailslot)是Windows操作系统提供的一种进程间通信(IPC, Inter-Process Communication)机制,它允许不同进程之间交换小量数据。邮槽的概念源自传统的邮件系统,每个邮槽可以视为一个消息队列,一个进程(邮...

    vc 进程通信(剪贴板 命名管道 匿名管道 邮槽)

    邮槽是Windows操作系统提供的一种进程间通信方式,允许消息的广播和接收。创建邮槽通常使用`CreateMailslot()`函数,发送消息用`WriteFile()`,接收消息则用`GetMailslotInfo()`和`ReadFile()`。邮槽通信适用于多...

    使用邮槽的进程通信示例

    邮槽(Mailslot)是Windows操作系统提供的一种进程间通信(IPC, Inter-Process Communication)机制,主要用于在同一台计算机或网络中的不同进程之间传递消息。它简单易用,适合于发送少量数据,尤其适用于服务器向...

    通过邮槽实现跨网络进程间的一对多的单向通讯.txt

    通过邮槽实现的一对多单向通讯是一种简单有效的进程间通信方式,适用于轻量级的数据传输场景。虽然其功能相对有限,但对于某些特定的应用场景来说,邮槽提供了一种简单且实用的解决方案。对于开发人员来说,掌握这种...

    Windows系统编程之进程间通信

    Windows 的IPC(进程间通信)机制主要是异步管道和命名管道。(至于其他的IPC方式,例如内存映射、邮槽等这里就不介绍了) 管道(pipe)是用于进程间通信的共享内存区域。创建管道的进程称为管道服务器,而连接到这...

    Socket 进程通信(类似QQ的聊天程序)

    1. 源码文件:.cpp和.h文件,这些是C++源代码,定义了程序的逻辑和结构,包括Socket的使用、进程间通信的实现以及MFC的控件和事件处理。 2. 可执行程序:.exe文件,这是编译后的程序,可以直接运行在支持Windows系统...

    《VC++深入详解》第17章 进程间通信

    《VC++深入详解》第17章 进程间通信主要介绍了四种进程间通信机制:剪贴板、匿名管道、命名管道和邮槽。这些机制是实现不同进程间数据交换的关键,尤其在多任务和分布式系统中至关重要。 1. **剪贴板**:剪贴板是一...

    C++邮槽通讯demo

    邮槽和信号是Qt库中用于对象间通信的核心机制,它们遵循模型-视图-控制器(MVC)设计模式,提供了一种灵活、类型安全的方式来连接对象和响应事件。以下是关于邮槽通信的详细知识点: 1. **信号与信号/槽机制**:在...

Global site tag (gtag.js) - Google Analytics