简介
命名管道是一种命名的可以在管道服务器进程与管道客户进程进行单向或双向通信的一种机制。命名管道即可以是基于消息的也可以是基于字节流的。命名管道既可以实现同一台电脑上的进程间的通信,也可以实现基于网络的不同电脑上的进程间的通信,当然同一个进程即可以是服务端也可以是客户端。一个命名管道的多个实例可以共享同一个管道名称,但每个实例具有独立的缓冲区和句柄,因此每个实例可以同时与不同管道客户端进行通信而不互相影响,但是同一时刻,同一个实例只能与一个客户端进行通信。
命名管道服务端
服务端通过CreateNamePipe创建命名管道,以下是其函数声明
HANDLE WINAPI CreateNamedPipe(
_In_ LPCTSTR lpName,
_In_ DWORD dwOpenMode,
_In_ DWORD dwPipeMode,
_In_ DWORD nMaxInstances,
_In_ DWORD nOutBufferSize,
_In_ DWORD nInBufferSize,
_In_ DWORD nDefaultTimeOut,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
- lpName表示管道名称,必须是如下形式\.\pipe\pipename,小数点表示本地机器,因此不能在远程机器上创建管道,管道名称大小写不敏感,最长不能超过256个字符。
- dwOpenMode表示打开模式,该参数必须设置如下三个互斥标志中的一个:PIPE_ACCESS_DUPLEX(管道既可以读又可以写),PIPE_ACCESS_INBOUND(管道只能读不能写),PIPE_ACCESS_OUTBOUND(管道只能写不能读)。该参数还可以包含如下标志中的一个或多个:FILE_FLAG_FIRST_PIPE_INSTANCE (表示只有第一个管道实例可以创建成功,即使nMaxInstances参数设置为多个),FILE_FLAG_WRITE_THROUGH(此标志只对基于网络的字节流模式的管道起作用,当设置此标志时,当程序向管道写数据时,只有当所有数据写入到远端缓存区时才返回),FILE_FLAG_OVERLAPPED (是否启用重叠IO又叫异步IO,当此标志设置时,程序可以同一个线程并发访问管道的多个实例,也可以在一个管道实例上同时执行读和写操作)。多个标志用”|”分割。
- dwPipeMode用来设置管道模式,该参数必须包含如下互斥标志中的一个:PIPE_TYPE_BYTE (表示管道是基于字节流的),PIPE_TYPE_MESSAGE (表示管道是基于消息的)。该参数还可以设置如下两组互斥标志中的一个或多个:PIPE_READMODE_BYTE ,PIPE_READMODE_MESSAGE ,表示管道读取模式是基于消息还是基于字节流的,PIPE_READMODE_MESSAGE只能与PIPE_TYPE_MESSAGE一起使用; PIPE_WAIT,PIPE_NOWAIT,表示管道读取,写入与等待连接是是否阻塞,PIPE_NOWAIT表示不阻塞,因为实现管道异步有更好的方法(重叠IO),所以这个标志总是设置为PIPE_WAIT。
- nMaxInstances表示最多可以创建同名管道的多少个实例,不能超过255,也可以设置为PIPE_UNLIMITED_INSTANCES,由系统根据自身资源来决定最多能创建多少个实例。一般有三种方式实现同名管道的多个实例的并发操作:1、为每一个连接上的实例创建一个线程执行读写,2、采用重叠结构来实现,3、采用完成端口来实现。
- nOutBufferSize输入缓冲区的大小
- nInBufferSize输入缓冲区的大小
- nDefaultTimeOut客户端连接时的默认超时时间,只有客户端调用WaitNamePipe函数并将nTimeOut参数设置为NMPWAIT_USE_DEFAULT_WAIT起作用,当设置为0时,表示为50ms
lpSecurityAttributes设置基于ACL访问控制属性。
返回值为管道实例句柄。
服务端通过ConnectNamedPipe函数等待客户端连接,函数声明如下:
BOOL WINAPI ConnectNamedPipe(
_In_ HANDLE hNamedPipe,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
- hNamePipe管道实例句柄
lpOverlapped 重叠IO结构,当打开模式设置为FILE_FLAG_OVERLAPPED 有效。
如果成功返回值为True,如果启用重叠IO结构当返回为FALSE,但是调用GetLastError返回值为ERROR_IO_PENDING也表示成功。
通过ReadFile,ReadFileEx函数来读取管道,通过WriteFile,WirteFileEx函数来写入管道。
以下为一个不使用重叠结构的单实例的管道服务端代码:
#include &