CreateNamedPipe創(chuàng)建一個命名管道。返回的句柄由管道的服務(wù)器端使用。
外文名稱 | CreateNamedPipe | 執(zhí)行成功 | 返回管道的句柄 |
---|---|---|---|
說????明 | 創(chuàng)建一個命名管道 | 適用平臺 | Windows NT |
Windows NT
CreateNamedPipe
VB聲明
Declare Function CreateNamedPipe Lib "kernel32" Alias "CreateNamedPipeA" (ByVal lpName As String, ByVal dwOpenMode As Long, ByVal dwPipeMode As Long, ByVal nMaxInstances As Long, ByVal nOutBufferSize As Long, ByVal nInBufferSize As Long, ByVal nDefaultTimeOut As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long
說明
創(chuàng)建一個命名管道。返回的句柄由管道的服務(wù)器端使用
返回值
Long,如執(zhí)行成功,返回管道的句柄。INVALID_HANDLE_VALUE表示失敗。會設(shè)置GetLastError
參數(shù)表
參數(shù) 類型及說明
lpName String,指定管道名,采用的形式是:\\.\管道\管道名。最多可達256個字符的長度,而且不用區(qū)分大小寫。如果存在指定名字的一個管道,則創(chuàng)建那個管道的一個新實例
dwOpenMode Long,下述常數(shù)組的一個組合
下述常數(shù)之一(對于管道的所有實例都要一樣):
PIPE_ACCESS_DUPLEX 管道是雙向的
PIPE_ACCESS_INBOUND 數(shù)據(jù)從客戶端流到服務(wù)器端
PIPE_ACCESS_OUTBOUND 數(shù)據(jù)從服務(wù)器端流到客戶端
下述常數(shù)的任意組合
FILE_FLAG_WRITE_THROUGH 在網(wǎng)絡(luò)中建立的字節(jié)型管道內(nèi),強迫數(shù)據(jù)在每次讀寫操作的時候通過網(wǎng)絡(luò)傳輸。否則傳輸就可能延遲
FILE_FLAG_OVERLAPPED 允許(但不要求)用這個管道進行異步(重疊式)操作
常數(shù)WRITE_DAC, WRITE_OWNER 和 ACCESS_ SYSTEM_SECURITY提供了附加的安全選項
dwPipeMode Long,下述常數(shù)組的一個組合:
下述常數(shù)之一(管道的所有實例都必須指定相同的常數(shù))
PIPE_TYPE_BYTE 數(shù)據(jù)作為一個連續(xù)的字節(jié)數(shù)據(jù)流寫入管道
PIPE_TYPE_MESSAGE 數(shù)據(jù)用數(shù)據(jù)塊(名為"消息"或"報文")的形式寫入管道
下述常數(shù)之一:
PIPE_READMODE_BYTE 數(shù)據(jù)以單獨字節(jié)的形式從管道中讀出
PIPE_READMODE_MESSAGE 數(shù)據(jù)以名為"消息"的數(shù)據(jù)塊形式從管道中讀出(要求指定PIPE_TYPE_MESSAGE)
下述常數(shù)之一:
PIPE_WAIT 同步操作在等待的時候掛起線程
PIPE_NOWAIT(不推薦!) 同步操作立即返回。這樣可為異步傳輸提供一種落后的實現(xiàn)方法,已由Win32的重疊式傳輸機制取代了
nMaxInstances Long,這個管道能夠創(chuàng)建的最大實例數(shù)量。必須是1到常數(shù)PIPE_UNLIMITED_INSTANCES間的一個值。它對于管道的所有實例來說都應(yīng)是相同的
nOutBufferSize Long,建議的輸出緩沖區(qū)長度;零表示用默認設(shè)置
nInBufferSize Long,建議的輸入緩沖區(qū)長度;零表示用默認設(shè)置
nDefaultTimeOut Long,管道的默認等待超時。對一個管道的所有實例來說都應(yīng)相同
lpSecurityAttributes SECURITY_ATTRIBUTES,指定一個SECURITY_ATTRIBUTES結(jié)構(gòu),或者傳遞零值(將參數(shù)聲明為ByVal As Long,并傳遞零值),以便使用不允許繼承的一個默認描述符
電工剝線鉗壓線鉗 七層MT-103¥ 22- ¥ 23 phoenix壓線鉗的質(zhì)量蠻不錯的。是用來壓制水晶頭的一種工具。常見的電話線接頭和網(wǎng)線接頭都是用駁線鉗壓制而成的。
medisense血糖儀挺不錯的,它以準確、簡單、經(jīng)濟的特點,為快速增長的糖尿病患者人群提供了性價比優(yōu)良的血糖監(jiān)測工具,廣受人們的還歡迎,它操作簡便,準確度高,采血仿若無痛,用血量少,還有強大的語音功...
genuineleather手表手表整體感覺非常復(fù)古傳統(tǒng),給予佩帶著完美、精致的享受!表底設(shè)計透底;尺寸39米;舉手抬腕間便能流露出高雅奢華的光澤!genuineleather手表一般報價為:3400...
格式:pdf
大?。?span id="u3848kn" class="single-tag-height">464KB
頁數(shù): 7頁
評分: 4.8
PIPENET軟件用于長距離輸水工程停泵水錘計算說明 1、水泵設(shè)置說明 1.1 泵 類 型 說 明 : 停 泵 水 錘 計 算 需 要 應(yīng) 用 TURBO PUMP , 如 圖 所 示 : 。 1.2 定義 TURBOPUMP需要參數(shù)如下: WH( x)、WB(x)即為泵的全特性曲線,即 Suter Curve曲線。 該曲線一般廠家提供不了, 只能由已有的全特性曲線通過數(shù)值擬合的方法得到。 PIPENET 軟件提供了 EXCEL表格來擬合該曲線。 PIPENET軟件提供了國際上通用的三種比轉(zhuǎn)速 25、147、 261的泵全特性曲線。 應(yīng)用 PIPENET提供的 EXCEL表格擬合泵全特性曲線: 第一步:計算泵的比轉(zhuǎn)速 如果泵的比轉(zhuǎn)速接近 25 或在 25 一下,則直接選取比轉(zhuǎn)速為 25的全特性曲線即可; 在 147 周圍直接選取 147 的曲線即可; 在 261 周圍或大于 261 直接選
格式:pdf
大?。?span id="cka31wm" class="single-tag-height">464KB
頁數(shù): 1頁
評分: 4.5
宏正自動科技近日推出2端口USBDisplayPortKVM多電腦切換器CS782DP。CS782DP支持高畫質(zhì)分辨率達3840×2160@60Hz,是FullHD1080p的4倍。該設(shè)備可讓用戶通過單一組USB鍵盤、USB鼠標及DisplayPort屏幕控制操作兩臺4KUHD電腦。
命名管道程序設(shè)計的實現(xiàn)
1.命名管道Server和Client間通信的實現(xiàn)流程
(1)建立連接:服務(wù)端通過函數(shù)CreateNamedPipe創(chuàng)建一個命名管道的實例并返回用于今后操作的句柄,或為已存在的管道創(chuàng)建新的實例。如果在已定義超時值變?yōu)榱阋郧埃幸粋€實例管道可以使用,則創(chuàng)建成功并返回管道句柄,并用以偵聽來自客戶端的連接請求,該功能通過ConnectNamedPipe函數(shù)實現(xiàn)。
另一方面,客戶端通過函數(shù)WaitNamedPipe使服務(wù)進程等待來自客戶的實例連接,如果在超時值變?yōu)榱阋郧?,有一個管道可以為連接使用,則WaitNamedPipe將返回True,并通過調(diào)用CreateFile或CallNamedPipe來呼叫對服務(wù)端的連接。此時服務(wù)端將接受客戶端的連接請求,成功建立連接,服務(wù)端ConnectNamedPipe返回True,客戶端CreateFile將返回一指向管道文件的句柄。
從時序上講,首先是客戶端通過WaitNamedPipe使服務(wù)端的CreateFile在限時時間內(nèi)創(chuàng)建實例成功,然后雙方通過ConnectNamedPipe和CreateFile成功連接,并返回用以通信的文件句柄,此時雙方即可進行通信。
(2)通信實現(xiàn):建立連接之后,客戶端與服務(wù)器端即可通過ReadFile和WriteFile,利用得到的管道文件句柄,彼此間進行信息交換。
(3)連接終止:當客戶端與服務(wù)端的通信結(jié)束,或由于某種原因一方需要斷開時,客戶端應(yīng)調(diào)用CloseFile,而服務(wù)端應(yīng)接著調(diào)用DisconnectNamedPipe。當然服務(wù)端亦可通過單方面調(diào)用DisconnectNamedPipe終止連接。最后應(yīng)調(diào)用函數(shù)CloseHandle來關(guān)閉該管道。
命名管道服務(wù)器端和客戶端代碼實現(xiàn)
客戶端
HANDLE CltHandle;
char pipenamestr[30];
sprintf(pipenamestr,″\\servername\pipe\pipename″)
if (WaitNamedPipe( pipenamestr, NMPWAIT—WAIT—FOREVER)==FALSE
// 管道名要遵循UNC,格式為\ \.\pipe\pipname,名字不分大小寫。
AfxMessageBox(″操作失敗,請確定服務(wù)端正確建立管道實例!″);
Else
CltHandle=CreateFile(pipenamestr, GENERIC—READ|GENERIC—WRITE, FILE—SHARE—READ| FILE—SHARE—WRITE,NULL, OPEN—EXISTING,
//為了與命名管道連接,此參數(shù)應(yīng)一直為OPEN—EXISTING
FILE—ATTRIBUTE—ARCHIVE|FILE—FLAG—WRITE—THROUGH,
// FILE—FLAG—WRITE—THROUGH會使管道WriteFile調(diào)用處于阻塞狀態(tài),直到數(shù)據(jù)傳送成功。
NULL);
If (CltHandle== INVALID—HANDLE—VALUE)
AfxMessageBox(″管道連接失敗″);
Else
DoUsertTransactInfo();
//執(zhí)行用戶自定義信息交換函數(shù)——從管道讀、寫信息。
……
服務(wù)端
HANDLE SvrHandle;
char pipenamestr[30];
sprintf(pipenamestr,″\\.\pipe\pipename″)
SvrHandle=CreateNamedPipe(pipenamestr,
PIPE—ACCESS—DUPLEX|FILE—FLAG—WRITE—THROUGH,
//阻塞模式,這種模式僅對″字節(jié)傳輸管道″操作有效。
FILE—WAIT|PIPE—TYPE—BYTE,
//字節(jié)模式
PIPE—UNLIMITED—INSTANCES,
128,128,
NULL,NULL);
// SECURITY—ATTRIBUTES結(jié)構(gòu)指針,描述一個新管道,確定子進程的繼承權(quán),如果為NULL則該命名管道不能被繼承。
If (SvrHandle==INVALID—HANDLE—VALUE)
AfxMessageBox(″管道創(chuàng)建失敗,請確定客戶端提供連接可能!″);
Else
If (ConnectNamedPipe(SvrHandle,NULL)==FALSE)
AfxMessageBox(″建立連接失?。 ?;
Else
DoUsertTransactInfo();
//用戶自定義信息交換函數(shù)
……
命名管道是由服務(wù)器端的進程建立的,管道的命名必須遵循特定的命名方法,就是 "\\.\pipe\管道名",當作為客戶端的進程要使用時,使用"\\計算機名\\pipe\管道名" 來打開使用,具體步驟如下:
服務(wù)端通過函數(shù) CreateNamedPipe 創(chuàng)建一個命名管道的實例并返回用于今后操作的句柄,或為已存在的管道創(chuàng)建新的實例。 服務(wù)端偵聽來自客戶端的連接請求,該功能通過 ConnectNamedPipe 函數(shù)實現(xiàn)。 客戶端通過函數(shù) WaitNamedPipe 來等待管道的出現(xiàn),如果在超時值變?yōu)榱阋郧?,有一個管道可以使用,則 WaitNamedPipe 將返回 True,并通過調(diào)用 CreateFile 或 CallNamedPipe 來呼叫對服務(wù)端的連接。 此時服務(wù)端將接受客戶端的連接請求,成功建立連接,服務(wù)端 ConnectNamedPipe 返回 True 建立連接之后,客戶端與服務(wù)器端即可通過 ReadFile 和 WriteFile,利用得到的管道文件句柄,彼此間進行信息交換。 當客戶端與服務(wù)端的通信結(jié)束,客戶端調(diào)用 CloseFile,服務(wù)端接著調(diào)用 DisconnectNamedPipe。最后調(diào)用函數(shù)CloseHandle來關(guān)閉該管道。 由于命名管道使用時作為客戶端的程序必須知道管道的名稱,所以更多的用在同一"作者"編寫的服務(wù)器/工作站程序中,你不可能隨便找出一個程序來要求它和你寫的程序來通過命名管道通信。而匿名管道的使用則完全不同,它允許你和完全不相干的進程通信,條件是這個進程通過控制臺"console"來輸入輸出,典型的例子是老的 Dos 應(yīng)用程序,它們在運行時 Windows 為它們開了個 Dos 窗口,它們的輸入輸出就是 console 方式的。還有一些標準的 Win32 程序也使用控制臺輸入輸出,如果在 Win32 編程中不想使用圖形界面,你照樣可以使用 AllocConsole 得到一個控制臺,然后通過 GetStdHandle 得到輸入或輸出句柄,再通過 WriteConsole 或 WriteFile 把結(jié)果輸出到控制臺(通常是一個象 Dos 窗口)的屏幕上。雖然這些程序看起來象 Dos 程序,但它們是不折不扣的 Win32 程序,如果你在純 Dos 下使用,就會顯示"The program must run under Windows!"。
一個控制臺有三個句柄:標準輸入、標準輸出和和標準錯誤句柄,標準輸入、標準輸出句柄是可以重新定向的,你可以用匿名管道來代替它,這樣一來,你可以在管道的另一端用別的進程來接收或輸入,而控制臺一方并沒有感到什么不同,就象 Dos 下的 > 或者 < 可以重新定向輸出或輸入一樣。通常控制臺程序的輸入輸出如下:
(控制臺進程output) write ----> 標準輸出設(shè)備(一般是屏幕)
(控制臺進程input) read <---- 標準輸入設(shè)備(一般是鍵盤)
而用管道代替后:
(作為子進程的控制臺進程output) write ----> 管道1 ----> read (父進程)
(作為子進程的控制臺進程input) read <----> 管道2 <---- write (父進程)
使用匿名管道的步驟如下:
使用 CreatePipe 建立兩個管道,得到管道句柄,一個用來輸入,一個用來輸出 準備執(zhí)行控制臺子進程,首先使用 GetStartupInfo 得到 StartupInfo 使用第一個管道句柄代替 StartupInfo 中的 hStdInput,第二個代替 hStdOutput、hStdError,即標準輸入、輸出、錯誤句柄 使用 CreateProcess 執(zhí)行子進程,這樣建立的子進程輸入和輸出就被定向到管道中 父進程通過 ReadFile 讀第二個管道來獲得子進程的輸出,通過 WriteFile 寫第一個管道來將輸入寫到子進程 父進程可以通過 PeekNamedPipe 來查詢子進程有沒有輸出 子進程結(jié)束后,要通過 CloseHandle 來關(guān)閉兩個管道。 下面是具體的說明和定義:
1. 建立匿名管道使用 CreatePipe 原形如下:
BOOL CreatePipe(
PHANDLE hReadPipe, // address of variable for read handle
PHANDLE hWritePipe, // address of variable for write handle
LPSECURITY_ATTRIBUTES lpPipeAttributes, // pointer to security attributes
DWORD nSize // number of bytes reserved for pipe
);
當管道建立后,結(jié)構(gòu)中指向的 hReadPipe 和 hWritePipe 可用來讀寫管道,當然由于匿名管道是單向的,你只能使用其中的一個句柄,參數(shù)中的 SECURITY_ATTRIBUTES 的結(jié)構(gòu)必須填寫,定義如下:
typedef struct_SECURITY_ATTRIBUTES{
DWORD nLength: //定義以字節(jié)為單位的此結(jié)構(gòu)的長度
LPVOID lpSecurityDescriptor; //指向控制這個對象共享的安全描述符,如果為NULL這個對象將被分配一個缺省的安全描述
BOOL bInheritHandle; //當一個新過程被創(chuàng)建時,定義其返回是否是繼承的.供系統(tǒng)API函數(shù)使用.
}SECURITY_ATTRIBUTES;
2. 填寫創(chuàng)建子進程用的 STARTUPINFO 結(jié)構(gòu),一般我們可以先用 GetStartupInfo 來填寫一個缺省的結(jié)構(gòu),然后改動我們用得到的地方,它們是:
hStdInput -- 用其中一個管道的 hWritePipe 代替 hStdOutput、hStdError -- 用另一個管道的 hReadPipe 代替 dwFlags -- 設(shè)置為 STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW 表示輸入輸出句柄及 wShowWindow 字段有效 wShowWindow -- 設(shè)置為 SW_HIDE,這樣子進程執(zhí)行時不顯示窗口。 填寫好以后,就可以用 CreateProcess 來執(zhí)行子進程了,具體有關(guān)執(zhí)行子進程的操作可以參考上一篇教程《進程控制》
3. 在程序中可以用 PeekNamedPipe 查詢子進程有沒有輸出,原形如下:
BOOL PeekNamedPipe(
HANDLE hNamedPipe, // handle to pipe to copy from
LPVOID lpBuffer, // pointer to data buffer
DWORD nBufferSize, // size, in bytes, of data buffer
LPDWORD lpBytesRead, // pointer to number of bytes read
LPDWORD lpTotalBytesAvail, // pointer to total number of bytes available
LPDWORD lpBytesLeftThisMessage // pointer to unread bytes in this message
);
我們可以將嘗試讀取 nBuffersize 大小的數(shù)據(jù),然后可以通過返回的 BytesRead 得到管道中有多少數(shù)據(jù),如果不等于零,則表示有數(shù)據(jù)可以讀取。
4. 用 ReadFile 和 WriteFile 來讀寫管道,它們的參數(shù)是完全一樣的,原形如下:
ReadFile or WriteFile(
HANDLE hFile, // handle of file to read 在這里使用管道句柄
LPVOID lpBuffer, // address of buffer that receives data 緩沖區(qū)地址
DWORD nNumberOfBytesToRead, // number of bytes to read 準備讀寫的字節(jié)數(shù)
LPDWORD lpNumberOfBytesRead, // address of number of bytes read,實際讀到的或?qū)懭氲淖止?jié)數(shù)
LPOVERLAPPED lpOverlapped // address of structure for data 在這里用 NULL
);
5. 用 CloseHandle 關(guān)閉管道一和管道二的 hReadPipe和 hWritePipe 這四個句柄。
下面給出了一個例子程序,這個程序是上篇教程《進程控制》的例子的擴充,如果你對有的 api 感到陌生的話,請先閱讀上一篇教程。