命名管道概述

命名管道(Named Pipes),顾名思义,一个有名字的管道。命名管道的名字主要是用于确保多个进程访问同一个对象。命名管道不仅可以在同一台计算机之间传输数据,甚至能在跨越一个网络的不同计算机的不同进程之间,支持可靠的、单向或双向的数据通信。

命名管道常用的API

创建命名管道实例—CreateNamedPipe

函数原型

HANDLE CreateNamedPipeW([in]           LPCWSTR               lpName,[in]           DWORD                 dwOpenMode,[in]           DWORD                 dwPipeMode,[in]           DWORD                 nMaxInstances,[in]           DWORD                 nOutBufferSize,[in]           DWORD                 nInBufferSize,[in]           DWORD                 nDefaultTimeOut,[in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
  • 参数lpName

唯一的管道名称。 必须是"\\.\pipe\管道名称“的格式。最多为256个字符长度,且不区分大小。如果已经有相同的命名管道,则会创建那个管道的一个实例

  • 参数dwOpenMode

表示管道的打开方式,同一管道的每个实例必须指定相同的打开方式

模式 意义

PIPE_ACCESS_DUPLEX

0x00000003

管道是双向的;服务器和客户端进程都可以读取和写入管道。

PIPE_ACCESS_INBOUND

0x00000001

管道中的数据流仅从客户端传输到服务器。

PIPE_ACCESS_OUTBOUND

0x00000002

管道中的数据流仅从服务器传输到客户端。

同时可以包含以下一个或多个标记,对于同一管道的不同实例,这些模式可以不同

模式 意义

FILE_FLAG_FIRST_PIPE_INSTANCE

0x00080000

如果尝试使用此标志创建管道的多个实例,则第一个实例的创建成功,但下一个实例的创建失败,并ERROR_ACCESS_DENIED

FILE_FLAG_WRITE_THROUGH

0x80000000

直写模式已启用。

FILE_FLAG_OVERLAPPED

0x40000000

重叠模式已启用。

还可以包含以下安全访问模式的组合,对于同一管道的不同实例,这些模式可以是不同。

模式 意义

WRITE_DAC

0x00040000L

调用方将具有对命名管道的自由访问控制列表 (ACL) 的写入访问权限。

WRITE_OWNER

0x00080000L

调用方将具有对命名管道所有者的写入访问权限。

ACCESS_SYSTEM_SECURITY

0x01000000L

调用方将具有对命名管道的 SACL 的写入访问权限。有关详细信息,请参阅访问控制列表 (ACL) 和SACL 访问权限。
  • 参数dwPipeMode

管道模式,可以指定以下类型模式之一。必须为管道的每个实例指定为相同的类型模式

模式 意义

PIPE_TYPE_BYTE

0x00000000

数据以字节流的形式写入管道。

PIPE_TYPE_MESSAGE

0x00000004

数据作为消息流写入管道。

也可以指定以下读取模式之一。同一管道的不同实例可以指定不同的读取模式。

模式 意义

PIPE_READMODE_BYTE

0x00000000

数据以字节流的形式从管道读取。此模式可用于PIPE_TYPE_MESSAGEPIPE_TYPE_BYTE

PIPE_READMODE_MESSAGE

0x00000002

数据作为消息流从管道读取。仅当还指定了PIPE_TYPE_MESSAGE时,才能使用此模式。

还可以指定以下等待模式之一。同一管道的不同实例可以指定不同的等待模式。

PIPE_WAIT

0x00000000

阻止模式已启用。

PIPE_NOWAIT

0x00000001

非阻塞模式已启用。在此模式下,ReadFile,WriteFile和ConnectNamedPipe始终立即返回。

还可以指定以下远程客户端模式之一。同一管道的不同实例可以指定不同的远程客户端模式。

模式 意义

PIPE_ACCEPT_REMOTE_CLIENTS

0x00000000

可以接受来自远程客户端的连接,并根据管道的安全描述符进行检查。

PIPE_REJECT_REMOTE_CLIENTS

0x00000008

来自远程客户端的连接将自动被拒绝。
  • 参数nMaxInstances

指定管道可以创建的最大实例数,必须是1到常数255之间的一个值。管道的第一个实例可以指定这个值,管道的其他实例的这个值必须和第一个实例指定的这个值相同。

  • 参数nOutBufferSize

表示管道的输出缓冲区的容量,0表示使用默认大小。

  • 参数nInBufferSize

表示管道的输入缓冲区的容量,0表示使用默认大小

  • 参数nDefaultTimeOut

表示管道的默认等待超时(ms单位),零表示默认超时为50毫秒

  • 参数lpSecurityAttributes

指向SECURITY_ATTRIBUTES结构的指针,该结构体指定命名管道的安全描述符,并确定子进程是否继承返回的句柄。NULL表示使用默认安全描述符,并且无法继承句柄

函数返回值
函数执行成功返回命名管道的句柄,否则返回INVALID_HANDLE_VALUE

等待客户端连接—ConnectNamdePipe

函数原型

BOOL ConnectNamedPipe([in]                HANDLE       hNamedPipe,[in, out, optional] LPOVERLAPPED lpOverlapped
);
  • 参数hNamedPipe

表示管道的实例的服务端句柄。也就是CreateNamedPipe函数返回的句柄

  • 参数lpOverlapped

如果CreateNamedPipe第一个参数指定了FILE_FLAG_OVERLAPPED,则此参数不能为NULL,参数就必须是一个手动重置事件对象的句柄。

例如下面这样

//创建命名管道
hNamedPipe = CreateNamedPipe(.., PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,..);//手动重置事件对象的句柄
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//创建一个OVERLAPPED结构体
OVERLAPPED ovlap;
ZeroMemory(&ovlap, sizeof(OVERLAPPED));//底层调用的memset
ovlap.hEvent = hEvent;//等待客户端连接
ConnectNamedPipe(hNamedPipe,&ovlap);

客户端连接命名管道—WaitNamedpipe

BOOL WaitNamedPipeW([in] LPCWSTR lpNamedPipeName,[in] DWORD   nTimeOut
);
  • 参数lpNamedPipeName

表示命名管道的名称

  • 参数nTimeOut

表示等待命名管道的实例可用的毫秒数。可以使用以下值之一,而不是指定毫秒数。

取值 意义

NMPWAIT_USE_DEFAULT_WAIT

0x00000000

超时间隔是服务器进程在CreateNamedPipe函数中指定的默认值。

NMPWAIT_WAIT_FOREVER

0xffffffff

在命名管道的实例可用之前,该函数不会返回。

函数返回值

如果管道的实例在超时之前可用,则返回值非零。否则返回零 。

如果指定的命名管道不存在实例,则无论超时值设定如何,WaitNamedPipe函数会立即返回。

如果函数执行成功,则进程可以使用CreateFile函数打开命名管道句柄。返回TRUE表示至少有一个管道实例可用。但也可能打开失败,例如当服务器关闭或者有其他客户端打开了管道。

打开文件或I/O设备—CreateFile

HANDLE CreateFileA([in]           LPCSTR                lpFileName,[in]           DWORD                 dwDesiredAccess,[in]           DWORD                 dwShareMode,[in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes,[in]           DWORD                 dwCreationDisposition,[in]           DWORD                 dwFlagsAndAttributes,[in, optional] HANDLE                hTemplateFile
);
  • 参数lpFileName

表示创建或打开的文件或设备名称

  • 参数dwDesiredAccess

请求文件或设备的访问权限,有读、写、读写或无任何操作。GENERIC_READGENERIC_WRITE或两者(GENERIC_READ | GENERIC_WRITE

  • 参数dwShareMode

文件或设备的请求共享模式,有读、写、读写、删除、读写删或者无任何模式

价值 意义

0

防止其他进程在请求删除、读取或写入访问权限时打开文件或设备。

FILE_SHARE_DELETE

对文件或设备启用后续打开操作以请求删除访问权限。

FILE_SHARE_READ

启用对文件或设备的后续打开操作以请求读取访问权限。

FILE_SHARE_WRITE

允许对文件或设备执行后续打开操作以请求写入访问权限。
  • 参数 lpSecurityAttributes

指向SECUTITY_ATTRIBUTES结构的指针,参数为NULL表示任何子进程都不能继承CreateFile返回的句柄

  • 参数dwCreationDisposition

表示对存在会不存在的文件或设备执行的操作,对存在的文件或设备通常设置为OPEN_EXISTING

取值 意义

CREATE_ALWAYS

始终创建新文件。

CREATE_NEW

仅当文件尚不存在时才创建新文件。

OPEN_ALWAYS

始终打开文件。

OPEN_EXISTING

仅打开文件或设备(如果存在)。

TRUNCATE_EXISTING

打开文件并将其截断,使其大小为零字节(仅当它存在时)。
  • 参数dwFlagsAndAttributes

表示文件或设备属性和标志,FILE_ATTRIBUTE_NORMAL是文件的通用默认属性

  • 参数hTemplateFile

此参数可为NULL,打开现有文件时,创建文件时可用忽略这个参数

函数返回值

函数执行成功,返回值是指定文件、设备、命名管道或邮槽

函数失败返回INVALID_HANDLE_VALUE

Demo示例:

两个MFC应用,给第一个应用添加三个菜单分别为”创建管道“,”读取数据“,”写入数据“作为服务端。点击”创建管道“服务端会创建一个管道,然后等待连接;点击“读取数据”服务端会读取管道中的数据,然后通过消息提示框显示出来; 点击“写入数据”服务端会向命名管道写入数据。

第二个应用做客户端,为其添加三个菜单分别为“连接管道”、“读取数据”、“写入数据”。点击“连接管道”客户端会去连接命名管道;点击“读取数据”客户端会读取管道中的数据,然后通过消息提示框显示出来;点击“写入数据”客户端会向管道中写入数据。

服务端

创建管道:

服务端调ConnectNamedPipe等待客户端连接,这里我将参数lpOverlapped设定为一个手动重置的事件对象,当成功连接后,系统会将这个事件对象设为已通知状态,我们可以监听这个对象来判断客户端是否成功连接。

hNamedPipe是一个HANDLE类型的类属性,在类的构造函数里初始化,析构函数里销毁。

void CChildView::OnCreatNamePipe()
{//1.创建一个命名管道LPCTSTR szPipeName = TEXT("\\\\.\\pipe\\mypipe");hNamedPipe = CreateNamedPipe(szPipeName,PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,PIPE_TYPE_BYTE,1, 1024, 1024, 0, NULL);if (hNamedPipe == INVALID_HANDLE_VALUE) {TRACE("Create NamedPipe failed witch %d\n", GetLastError());MessageBox(_T("创建命名管道失败"));return;}//连接完成后,系统会将OVERLAPPED的hEvent设置为已通知状态事件//这里创建一个事件赋值给hEvent,用来监控其改变HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);if (hEvent == NULL) {MessageBox(_T("创建事件失败"));CloseHandle(hNamedPipe);hNamedPipe = NULL;return;}//2.等待客户端的连接OVERLAPPED ovlap;ZeroMemory(&ovlap, sizeof(OVERLAPPED));//底层调用的memsetovlap.hEvent = hEvent;if (!ConnectNamedPipe(hNamedPipe,&ovlap)) {//标准判断操作if (ERROR_IO_PENDING != GetLastError()) {MessageBox(_T("等待客户端连接失败"));CloseHandle(hNamedPipe);hNamedPipe = NULL;return;}}if (WaitForSingleObject(hEvent, INFINITE) == WAIT_FAILED) {//MessageBox(_T("等待对象失败"));CloseHandle(hNamedPipe);CloseHandle(hEvent);hNamedPipe = NULL;hEvent = NULL;return;}//否则就连接成功
}

读数据:

void CChildView::OnSreadNamePipe()
{char szBuf[100] = { 0 };DWORD dwRead;if (!ReadFile(hNamedPipe, szBuf, 100, &dwRead, NULL)) {MessageBox(_T("读取数据失败"));return;}MessageBox((CString)szBuf);
}

写数据:

void CChildView::OnSwriteNamePipe()
{char szBuf[] = "霸道小明超秀";DWORD dwWrite;if (!WriteFile(hNamedPipe, szBuf, strlen(szBuf) + 1, &dwWrite, NULL)) {MessageBox(_T("写入数据失败"));return;}
}

客户端

连接管道:

hNamedPipe是一个HANDLE类型是类属性,在构造函数里初始化,在析构函数里销毁。

void CChildView::OnConnectNamePipe()
{ //连接命名管道LPCTSTR szNamedPipe = TEXT("\\\\.\\pipe\\mypipe");if (0 == WaitNamedPipe(szNamedPipe, NMPWAIT_WAIT_FOREVER)) {MessageBox(_T("当前没有可以利用的管道"));return;}hNamedPipe = CreateFile(szNamedPipe,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);if (hNamedPipe == INVALID_HANDLE_VALUE) {TRACE("Create File failed with %d\n", GetLastError());MessageBox(_T("打开命名管道失败!"));hNamedPipe = NULL;return;}//连接成功
}

读数据:

void CChildView::OnReadNamePipe()
{char szBuf[100] = { 0 };DWORD dwRead;if (!ReadFile(hNamedPipe, szBuf, 100, &dwRead, NULL)) {MessageBox(_T("读取数据失败"));return;}MessageBox((CStringW)szBuf);
}

写数据:

void CChildView::OnWriteNamePipe()
{char szBuf[] = "霸道小明超秀";DWORD dwWrite;if(!WriteFile(hNamedPipe, szBuf, strlen(szBuf) + 1, &dwWrite, NULL)) {MessageBox(_T("写入数据失败"));return;}
}

执行结果:

进程的通信 - 命名管道相关推荐

  1. linux命名管道进程间通信,Linux进程间通讯--命名管道

    IPC安全 前面总结了匿名管道,如今来看命名管道:因为匿名管道的一个限制就是:只能是有血缘关系的进程间才能够通讯,好比:有两个同祖先的子进程,父子进程等:为了突破这一个限制,想让没有任何关系的两个进程 ...

  2. C# 管道通信-命名管道(一)

    最近在做一个应用程序,涉及到两个应用程序之间的通讯,就想到了用C#的命名管道的方式来实现,经过一番小折腾,总算实现了,现把一些主体的代码粘贴出来与大家分享: 管道通讯会涉及到client端和Serve ...

  3. 进程通信——命名管道

    目录 1.Creat 2.Open 3.Read/Write 4.Wait 5.Close 6.Delete 管道是 SylixOS 进程间通信的一种方式. 管道分为匿名管道 pipe 和命名管道 f ...

  4. 进程间通讯 ----- 命名管道

    进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.每个进程都有一个主线程,线程则是cpu调度的基本单位,每个进程都有自己的 ...

  5. linux 命名管道 c语言 不同进程,进程间通信 - 命名管道实现

    命名管道概述 命名管道是通过网络来完成进程之间的通信的,命名管道依赖于底层网络接口, 其中包括有 DNS 服务,TCP/IP 协议等等机制,但是其屏蔽了底层的网络协议细节, 对于匿名管道而言,其只能实 ...

  6. Linux —进程间的五种通信方式—(半双工管道、命名管道、消息队列、信号、共享内存),外加信号量。直接上代码:

    无名管道pipe(半双工):(仅限同一个程序运行) 创建无名管道会生成特殊文件,只存在于内存中 #include <stdio.h> #include <stdlib.h> # ...

  7. 进程间通信 - 命名管道实现

    引子 好,到这里呢,就需要介绍实现进程间通信的第四种方式了, 也就是通过命名管道来实现,前面介绍的那三种方式呢,都是有缺陷或者说局限性太强, 而这里介绍的命名管道相对来说,在这方面就做得好很多了, 比 ...

  8. 【Linux】进程间通信 - 匿名/命名管道与System V共享内存

    目录 前言 一.管道 0.什么是管道 1).管道的概念 2).管道的本质 3).管道指令: "|" 1.匿名管道 1).如何创建匿名管道 2).如何使用匿名管道进行通信 3).匿名 ...

  9. python 命名管道_命名管道实践

    命名管道技术实验 管道介绍 管道(Pipe)是一种进程间的通信机制,Windows.Linux和UNIX都使用这种机制. 管道是通过I/O接口存取的字节流创建管道后,通过使用操作系统的任何读或写I/O ...

最新文章

  1. 公众号留言-2020-4-1
  2. Python语言的特点
  3. 函数计算是如何工作的?
  4. Spring-学习笔记08【面向切面编程AOP】
  5. 服务器应用程序不可用您试图在此 Web 服务器上访问的 Web 应用程序当前不可用。请点击 Web 浏览器中的“刷...
  6. 寒冷的高纬度——我的梦开始的地方
  7. Magento用的哪个php框架,初识magento框架代码目录
  8. 零基础转行web前端,如何高效的去学习web前端?
  9. 10月2场CMDN Club活动专题、视频、资源分享
  10. 【阅读笔记】Implementation of tactical maneuvers with maneuver libraries
  11. URL编码的原因及场景
  12. warning: array subscript is above array bounds
  13. python格式化字符串固定宽度_python – 格式化固定宽度的字符串(unicode和utf8)
  14. ECCV2022 Workshop | 复杂环境中的多目标跟踪和分割
  15. 单例模式与反射的攻防之【 道高一尺,魔高一丈 】
  16. 求助:tp-link wr720n路由器,想刷打印服务器!
  17. 高温不怕热,GVS智能家居为你打造夏日清爽雅居
  18. pytorch BatchNorm参数详解,计算过程
  19. 【P9】Point to the Expression:Solving Algebraic Word Problems using the Expression-Pointer Transformer
  20. 卡迪夫大数据专业排名_大数据分析:英超大数据!布莱顿vs卡迪夫

热门文章

  1. tp5怎么跨控制器调用别的方法
  2. ulua中lua代码使用反射调用c#详解
  3. [附源码]计算机毕业设计Python+uniapp基于安卓的校园二手书籍交易APP1yh1y(程序+lw+APP+远程部署)
  4. 做一个laravel框架下的系统日志
  5. c语言运行后tecplot云图,tecplot执行fluent后处理截面云图显示.pdf
  6. uboot源码分析(基于S5PV210)之启动第一阶段
  7. 医学序列图像定位线绘制基本方法介绍
  8. monkeyrunner之夜神模拟器的安装与使用(二)
  9. 我的镜头观,尼康如何搭配镜头(!!强烈推荐!!) 转贴
  10. DotNetty TLS 开启双向认证加密传输数据