📄 17.3.1命名及 基础知识.txt
字号:
17.3 命名
17.3.1 基础知识
命名管道通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节。我们在不了解网络协议的
情况下,也可以利用命名管道来实现进程间的通信。上面介绍的匿名管道只能在本地机器上的父子
进程间进行通信,而命名管道不仅可以在本机上实现两个进程间的通信,还可以跨网络实现两个进
程间的通信。
命名管道充分利用了 WindowsNT和 Windows 2000内建的安全机制。在创建管道时,可以指定具有访
问权限的用户,而其他用户则不能访问这个管道。如果采用 Sockets编写网络应用,那么为了完成
用户身份验证需要程序员自行编码实现,而采用命名管道就不需要再编写身份验证的代码了。
将命名管道作为一种网络编程方案时,它实际上建立了一个客户机 /服务器通信体系,并在其中可
靠地传输数据。命名管道是围绕 Windows文件系统设计的一种机制,采用"命名管道文件系统
( Named Pipe File System, NPFS) "接口,因此,客户机和服务器可利用标准的 Win32文件系统函
数 (例如 ReadFile和 WriteFile )来进行数据的收发。命名管道服务器和客户机的区别在于:服务
器是惟一一个有权创建命名管道的进程,也只有它才能接受管道客户机的连接请求。而客户机只能
同一个现成的命名管道服务器建立连接。命名管道服务器只能在 Windows NT或 Windows 2000上创
建,因此,我们无法在两台 Windows 95或 Windows 98计算机之间利用管道进行通信。不过,客户
机可以是 Windows 95或 Windows 98计算机,与 Windows NT或 Windows 2000计算机进行连接通信。
命名管道提供了两种基本通信模式:字节模式和消息模式。在字节模式下,数据以一个连续的字节流
的形式在客户机和服务器之间流动。而在消息模式下,客户机和服务器则通过一系列不连续的数据
单位,进行数据的收发,每次在管道上发出了一条消息后,它必须作为一条完整的消息读入。
在程序中如果要创建一个命名管道,需要调用 CreateNamedPipe函数。该函数的原型声明如下所示:
HANDLE CreateNamedPipe(
LPCTSTR lpName ,
DWORD dwOpenMode,
DWORD dwPipeMode ,
DWORD nMaxlnstances
DWORD nOutBufferSize ,
DWORD ninBufferSize,
DWORD nDefaultTimeOut
LPSECURITY_ATTR工 BUTES lpSecurityAttributes
CreateNamedPipe函数创建一个命名管道的实例,井返回该命名管道的句柄。一个命名管道的服务器
进程使用该函数创建命名管道的第一个实例,并建立它的基本属性,或者
创建一个现有的命名管道的新实例。如果需要创建一个命名管道的多个实例,就需要多次调用
CreateNamedPipe函数。该函数各个参数的含义分别如下所述。
.lpName
一个指向空终止的字符串,该字符串的格式必须是:"\\.pipe\pipename"。其中该字符串开始是
两个连续的反斜杠,其后的圆点表示是本地机器,如果想要与远程的服务器建立连接,那么在这个
圆点位置处应指定这个远程服务器的名称。接下来是 "pipe"这个固定的字符串,也就是说这个字符
串的内容不能修改,但其大小写是无所谓的。最后是所创建的命名管道的名称。
. dwOpenMode
指定管道的访问方式、重叠方式、写直通方式,还有管道句柄的安全访问方式。这个参数的管道访
问方式必须是表 17.7所列值之一,并且管道的每一个实例都必须有同样的访问方式。
表 17.7命名管道的访问方式
管道访问方式 说明
PIPE_ACCESS_DUPLEX 双向模式,服务器进程和客户端进程都可以从管道读取数据和向管道中写入
数据。 该模式等价于指定 GE阳阳CREADIGE阳阳C WRITE。当客户端调用 CreateFile函数与管道连
接时,可以指定 GENE阳C_READ或 GENE阳C_WRITE.或者二者都指定
PIPE_ACCESS_INBOUND 管道中的数据流向只能是从客户端到服务器端进程,相当于指定 GENERIC_
阻AD, 也就是说,如果在服务器端创建命名管道时指定 PIPE_ACCESS_INBOUND访问方式,那么服务
器端就只能读取数据,而客户端就只能向管道写入数据
PIPE_ACCESS_OUTMOUND 管道中的数据流向只能是从服务器到客户端进程。服务器端只能向管道写
入数据, 而客户端只能从管道读取数据
该参数还可以包含表 17.8中所列出的标记中的一个或多个,用来指定写直通方式和重叠方式。
表 17.8写直通和重叠方式
写直通和重叠方式 说明
FILE_FLAG_'"吸Il E一ηfROUGH 允许写直通方式。该方式只影响对字节类型管道的写入操作,并
且只有当客户端与服务器端进程位于不同的计算机上时才有效。如果采用了该方式,那么只有等到
欲写入命名管 道的数据通过网络传送过去,并且放在了远程计算机的管道缓冲区中后,写数据的函
数才会成功返回。如果没有采用该方式,直到累积的字节数达到了簸小值,或超过了最大时间值
FILE FLAG OVERLAPPED 允许采用重叠模式,如果采用了该模式,那么那些可能会需要一定时间才
能完成的读写操作会立即返回。在重叠模式r.前台线程可以执行其他操作,而耗费时间的操作可以
在后台进行。例如,在重叠模式下,一个线程可以在管道的多个实例上同时处理输入和输出 操作,
或者在同一个管道句柄上同时执行读写操作。如果没有指定重叠模式,那么在管道句柄上执行的读
取和写入操作只有在这些操作完成之后才能返回。 R四1F11eEx和 WriteF11eEx函数只能在重叠模式
下使用管道句柄,而 R甜Ftle. WriteFile. conr胆创回回目lpe和币四皿创部副Pipe函数既可以以
重叠方式执行,也可以采用同步方式执行
关于重叠操作,前面已经介绍了,如果采用了重叠操作,对管道的读写函数将立即返回。当该操作
完成之后,系统会通过一种方式通知调用进程,本例将创建一个允许重叠操
作的命名管道。该参数还可以包含表 方式。 17.9中所列出的 标记中的一个或多个,用来指定管道
的安全访问
表17.9 安全访问方式
安全访问方式 说明
WRITE_DAC 调用者对命名管道的任意访问控制列表 (ACL)都可以进行写入访问
WRITE 0唱刑ER 调用者对命名管道的所有者可以进行写入访问
ACCESS_SYSTEM_SECURITY 调用者对命名管道的安全访问控制列表 (SACL)可以进行写入访问
. dwPipeMode
指定管道句柄的类型、读取和等待方式。管道句柄的类型可以取表17.10所列值之一。表17.10管道
句柄的类型
值 说明
PIPE_TYPE_BYTE 数据以字节流的形式写入管道,该方式不能在PIPE_READMODE_MESSAGE读方式下使
用
PIPE_TYPE_MESSAGE 数据以消息流的形式写入管道,该方式在 PIPE_READMODE_MESSAGE和 PIPE_
READMODE_BY'lE读方式下都可使用
读者应注意,同一个命名管道的每→个实例必须具有相同的类型。如果该参数值为0,那么默认是字
节类型方式。也就是说,通过这个参数,可以指定创建的是字节模式,还是消息模式的管道,如果
是 PIPE_TYPE_BY'IE,则创建的是字节模式,就不能和 PIPE_READMODE_MESSAGE读模式一起使用。
因为当把命名管道指定为消息模式时,系统发送消息时有一个定界符,当我们以消息读的模式去读
取时,通过该定界符就可以读取到一条完整的消息,但如果采用字节读方式读取,这时将忽略该定
界符而直接读取数据。所以,对消息模式的命名管道来说,可以采用消息读,也可以采用字节读的
方式读取数据。但是,对字节模式的命名管道来说,数据是一种字节流格式,没有定界符,因此如
果采用消息读的模式读取时,就不知道应该读取多少字节的数据才合适。
管道句柄的读取方式可以是表 17.11所列值之一,同一管道的不同实例可以指定不同的读取方式。
如果该值置为0,则默认是字节读方式。
表17.11管道旬柄的读取方式
管道句柄的读取方式 说明
PIPE_READMODE_BY'IE 以字节流的方式从管道读取数据。这种方式在 TYPE_MESSAGE类型下均可使
用
PIPE_TYPE_BY'IE和 PIPE_
PIPE_READMODE~如fESSAGE 以消息流的方式从管道读取数据"该方式只有在 下才可使用
PIPE_TYPE_MESSAGE类型
管道句柄的等待方式可以是表 17.12所列值之一,同一管道的不同实例可以取不同的等待方式。如
果该值设置为0,则默认是阻塞方式。
表 17.12管道旬柄的等待方式
管道句柄的等待方式 说明
PIPE_WAIT 允许阻塞方式,在这种方式下.&凹,iFile. WriteFile.或 Connec创amedPipe函数必须
等到读 取到了数据,或写入了所有数据,或有一个客户连接到来后才能返回。
PIPE_NOWAIT 允许非阻塞方式,在这种方式下. ReadFile. WriteFile.或 Conn饵创剧创Pipe函数
总是立即返回。
注意:为与Microsoft LAN Manager版本 2.0兼容,故支持非阻塞方式,它不应该用于实现命名管道
的异步输入/输出。
. nMaxInstances
指定管道能够创建的实例的最大数目。该参数的取值范围从 1到 PEE-UNLIMITED_INS 'fANCES。如
果是 PIPE_UNLIMITED_INSTANCES,那么可以创建的管道实例数目仅仅受限于系统可使用的资源。例
如,如果将这个参数值设置为 5,也就是说,最多可以创建该命名管道的 5个实例,那么这是否就
表示同时有 5个客户端能够连接到这个命名管道的实例上呢?实际上,这里所指的最大实例数目是指
对同一个命名管道最多所能创建的实例数目。如果希望同时能够连接 5个客户端,那么必须调用 5
次 CreateNamedPipe函数创建 5个命名管道实例,然后才能同时接收 5个客户端连接请求的到来。
对同一个命名管道的实例来说,在某一时刻,它只能和一个客户咽ιU皿阻。
. nOutBufferSize
指定为输出缓冲区所保留的字节数。
. nlnBufferSize
指定为输入缓冲区所保留的字节数。
实际上,输入和输出缓冲区的大小是可变的,保留给命名管道的每一端的实际缓冲区大小既可以是
系统默认值,也可以是系统最小值、系统最大值,或延伸到下一个分配边界的一个指定值。
. nDefaultTimeOut
指定默认的超时值,单位是 m。同一个管道的不同实例必须指定同样的超时值。
. lpSecurityA由ibutes
指向 SECURITY_ATIRmUIES结构的指针,该结构指定了命名管道的安全描述符,并确定子进程是否可
以继承这个函数返回的管道句柄。可以将这个参数设置为 NULL,让命名管道具有默认的安全描述符,
而且该句柄不能被继承。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -