管道式是进程进行通信时所用的一个共享内存段。创建管道的进程被称作管道服务器。连接到管道的进程称为管道用户。
管道分为两类,即命名管道和匿名管道。匿名管道比命名管道的花费要少,但是能提供的服务也少。
管道是信息传递的通道,具有两个端口,有单向管道和双向管道,对于单向管道,一个端口用于读取管道信息,另一个用于向管道写入信息,双向管道两个端点都可以用于读写。
Anonymous Pipes
匿名管道是未命名的,通常用于父子进程之间传输数据的单向管道。匿名管道通常用于本地事物,而不能用于网络间的传输。
Named Pipes
命名管道是命名了的,用于管道服务器和一个(或多个)管道客户端进行数据传输的单向或多向传输的管道。
一个命名管道的所有实例共用一个管道名,但每个实例都有自己的缓冲区和句柄,而且通过不同的管路进行数据通信。
任何进程都能使用命名管道,接受安全检查,这使得命名管道成为在相关,或无关进程之间进行传输的一种简易方式。
任何进程都可以同时是管道客服端和服务器端。
命名管道可以用于同一台电脑上的进程间的数据交换,也可以用于网络上不同电脑上的进程间的数据交换。
管道服务器端调用CreateNamedPipe函数创建管道实例,而且不能通过远程计算机调用,使用格式如下:
\\.\pipe\PipeName
PipeName指定管道名,管道名可与包含除反斜杠之外的任何字符。
整个管道名最长可达256个字符且大小写不敏感。这个管道名可以提供给客服端以便客户端连接到这个管道。
管道客服端通过CreateFile, WaitNamedPipe, CallNamedPipe
函数指定管道名,使用如下格式:
\\ServerName\pipe\PipeName
其中ServerName是远程计算机名或句点(表示本地计算机),PipeName指定管道名,管道名可与包含除反斜杠之外的任何字符。
整个管道名最长可达256个字符且大小写不敏感,这里管道名是由CreateFile调用者自己定义的。
一旦管道实例创建成功,即可调用CreateFile,CallNamedPipe连接管道,如果实例可用,CreateFile返回一个到客户端管道的句柄。
如果实例还不可用,可以用CallNamedPipe来等待,一直到实例可用为止。
管道服务器决定调用ConnectNamedPipe的管道客户端何时接通管道,ConnectNamedPipe会使管道句柄处于阻塞模式直到客户端连接上管道。
如果管道客户端和服务器端要结束对实例的使用,服务器端必须先调用FlushFileBuffers以确保管道中的数据都被客户端读取了。
FlushFileBuffers在客户端读取了管道中的所有数据后才返回。然后服务器端才调用DisconnectNamedPipe关闭管道和客户端的连接。
这个函数会使得客户端的管道句柄无效,并且管道中的数据全部丢失,即使连接还没有关闭。关闭连接后,服务器端调用CloseHandle
来关闭管道实例的句柄,当然也可以不关闭句柄,而是使另一个客户端与管道连接。
进程可以调用GetNamedPipeInfo来获取命名管道的信息。GetNamedPipeHandleState函数来获取管道句柄是处于等待,还是读写状态
SetNamedPipeHandleState函数来设置管道句柄,使之处于读写或等待状态。
Named Pipe Instances
单管道多实例的管道具有三种基本的分类:
1为每个管道的实例创建一个线路。如多线管道服务器。此方法最简单,但很占内存。
2通过overlapped操作将ReadFile, WriteFile,ConnectNamedPipe制定为overlapped类型
3通过使用ReadFileEx ,WriteFileEx函数来实现overlapped操作。
Named Pipe Type(写), Read, and Wait Modes
服务器端可以通过CreateNamedPipe函数的dwPipeMode参数指定管道模式,客户端可以通过CreateFile指定管道模式。
管道的Type(写), Readmode决定数据时如何写入,或读出管道的,可以是消息流和字节流。
管道的Wait Modes决定ReadFile, WriteFile, ConnectNamedPipe处理等待操作。
分两类,1,blocking-wait mode,这种模式下上面函数会无期限的等待管道另一端的操作结束。
2nonblocking-wait mode,这种模式下,函数不会无期限的等待操作完成,而是立刻返回。
ReadFile会在管道为空的时候被wait mode影响,blocking-wait mode会等待管道另一端向管道写入数据,直到管道数据有效。
在nonblocking-wait mode模式下,ReadFile会立刻返回0,而且调用GetLastError可以得到ERROR_NO_DATA的返回值。
WriteFile会在管道缓存区不足时受wait mode影响,blocking-wait mode会等待管道另一端从管道读出数据,直到管道空出足够的空间。
在nonblocking-wait mode模式下,WriteFile会在写入缓冲区能容纳的量的数据后立刻返回非0,或不写入数据直接返回非0。
在没有客户端连接到或等待连接到管道时进行ConnectNamedPipe会受wait mode影响。a blocking-wait下ConnectNamedPipe会等到有客户端成功连接上管道才返回,nonblocking-wait会立即返回0,调用GetLastError会收到ERROR_PIPE_LISTENING。
默认情况下,CreateNamedPipe , CreateFile选择的是blocking-wait mode。
Named Pipe Open Modes
管道服务端可以通过CreateNamedPipe函数的dwOpenMode参数指定管道的访问权限,overlap与否,write-through mode。
客户端通过CreateFile的dwDesiredAccess参数指定管道的如是打开模式。管道的客户端和服务端对管道
访问权限的设置必须对应,因为他们处在管道的不同端,如果客户端设置为管道只读,那么服务端必须设置为管道只写。
如果要获得或更改管道属性,那么必须具有FILE_READ_ATTRIBUTES,FILE_WRITE_ATTRIBUTES权限。
在overlapped模式下,函数能立刻返回而不必等待冗长的读写,连接操作完成,而函数调用者还可以在此时进行其他操作,
冗长的读写,连接操作完成会被移到后台运行。
write-through mode只在以字节流在管道客户端和服务端进行写操作时有效,在这种模式下,写操作函数
得在将数据写入远程管道之后才返回。管道的write-through mode在管道创建之后就不能再改变了。
而且,在服务端和客户端没相关要求。