?? 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 + -