命名管道作
管道服务器首次调用 CreateNamedPipe 函数时,它使用 nMaxInstances 参数指定可以同时存在的管道的最大实例数。 服务器可以重复调用 CreateNamedPipe 来创建管道的其他实例,前提是它不超过最大实例数。 如果函数成功,则每个调用都会向命名管道实例的服务器端返回句柄。
管道服务器创建管道实例后,管道客户端就可以通过调用 CreateFile 或 CallNamedPipe 函数来连接到它。 如果管道实例可用,CreateFile 将句柄返回到管道实例的客户端端。 如果没有可用的管道实例,管道客户端可以使用 WaitNamedPipe 函数等待管道可用。
管道服务器可以通过调用 ConnectNamedPipe 函数来确定管道客户端何时连接到管道实例。 如果管道句柄处于阻塞等待模式,ConnectNamedPipe 在客户端连接之前不会返回。
管道客户端和服务器可以调用多个函数之一(除了 CallNamedPipe)来读取和写入命名管道。 这些函数的行为取决于管道的类型以及指定管道句柄生效的模式,如下所示:
- ReadFile 和 WriteFile 函数可用于字节类型管道或消息类型管道。
- 如果为重叠作打开管道句柄,ReadFileEx 和 WriteFileEx 函数可与字节类型管道或消息类型管道一起使用。
- PeekNamedPipe 函数可用于读取,而无需删除字节类型管道或消息类型管道的内容。 PeekNamedPipe 还可以返回有关管道实例的其他信息。
- 如果调用进程的管道句柄设置为消息读取模式,则可以将 TransactNamedPipe 函数与消息类型双工管道一起使用。 该函数写入请求消息并在单个作中读取回复消息,从而提高网络性能。
管道服务器在管道客户端启动之前不应执行阻止读取作。 否则,可能会发生争用情况。 在初始化代码(如 C 运行时库的初始化代码)需要锁定和检查继承的句柄时,通常会发生这种情况。
当客户端和服务器使用管道实例完成后,服务器应首先调用 FlushFileBuffers 函数,以确保客户端读取写入管道的所有字节或消息。 FlushFileBuffers 在客户端从管道读取所有数据之前不会返回。 然后,服务器调用 DisconnectNamedPipe 函数以关闭与管道客户端的连接。 此函数使客户端的句柄无效(如果尚未关闭)。 管道中的任何未读数据将被丢弃。 客户端断开连接后,服务器调用 CloseHandle 函数将其句柄关闭到管道实例。 或者,服务器可以使用 ConnectNamedPipe,使新客户端能够连接到管道的此实例。
进程可以通过调用 GetNamedPipeInfo 函数来检索有关命名管道的信息,该函数返回管道的类型、输入和输出缓冲区的大小以及可创建的管道实例的最大数目。 GetNamedPipeHandleState 函数报告管道句柄的读取和等待模式、当前管道实例数,以及通过网络通信的管道的其他信息。 SetNamedPipeHandleState 函数设置管道句柄的读取模式和等待模式。 对于与远程服务器通信的管道客户端,该函数还控制收集的最大字节数或传输消息之前等待的最大时间(假设客户端的句柄未在启用写通模式的情况下打开)。