日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

管道实现进程间通讯 、WaitNamedPipe

發布時間:2024/4/15 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 管道实现进程间通讯 、WaitNamedPipe 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?

一、管道實現進程間通訊

主要的理論知識
  1.什么是管道以及分類
  管道是兩個頭的東西,每一個頭各連接一個進程或者同一個進程的不同代碼,依照管道的類別分有兩種管道,匿名的和命名的;依照管道的傳輸方向分也能夠分成兩種,單向的雙向的。依據管道的特點,命名管道通經常使用在網絡環境下不同計算機上執行的進程之間的通信(當然也能夠用在同一臺機的不同進程中)它能夠是單向或雙向的;而匿名管道僅僅能用在同一臺計算機中,它僅僅能是單向的。匿名管道事實上是通過用給了一個指定名字的有名管道來實現的   使用管道的優點在于:讀寫它使用的是對文件操作的 api,結果操作管道就和操作文件一樣。即使你在不同的計算機之間用命名管道來通信,你也不必了解和自己去實現網絡間通信的詳細細節。
  2.管道的使用
  A.命名管道

  命名管道是由server端的進程建立的,管道的命名必須遵循特定的命名方法,就是"//./pipe/管道名"當作為client的進程要使用時,使用"//計算機名//pipe/管道名"來打開使用,詳細過程例如以下:

  服務端通過函數CreateNamedPipe創建一個命名管道的實例并返回用于今后操作的句柄,或為已存在的管道創建新的實例。服務端偵聽來自client的連接請求,該功能通過ConnectNamedPipe函數實現。

  client通過函數WaitNamedPipe來等待管道的出現,假設在超時值變為零曾經,有一個管道能夠使用,則WaitNamedPipe將返回 True,并通過調用CreateFileCallNamedPipe來呼叫對服務端的連接。

  此時服務端將接受client的連接請求,成功建立連接,服務端ConnectNamedPipe返回 True 建立連接之后,client與server端就可以通過ReadFileWriteFile,利用得到的管道文件句柄,彼此間進行信息交換。當client與服務端的通信結束,client調用CloseFile,服務端接著調用DisconnectNamedPipe。最后調用函數CloseHandle來關閉該管道。

  B.匿名管道

  因為命名管道使用時作為client的程序必須知道管道的名稱,所以很多其它的用在同一作者編寫的server/工作站程序中,你不可能隨便找出一個程序來要求它和你寫的程序來通過命名管道通信。而匿名管道的使用則全然不同,它同意你和全然不相干的進程通信,條件是這個進程通過控制臺“console”來輸入輸出,典型的樣例是老的 Dos 應用程序,它們在執行時 Windows為它們開了個 Dos窗體,它們的輸入輸出就是 console方式的。另一些標準的 Win32程序也使用控制臺輸入輸出,假設在 Win32編程中不想使用圖形界面,你照樣能夠使用AllocConsole得到一個控制臺,然后通過GetStdHandle得到輸入或輸出句柄,再通過WriteConsoleWriteFile把結果輸出到控制臺(一般是一個象 Dos窗體)的屏幕上。盡管這些程序看起來象 Dos程序,但它們是不折不扣的 Win32程序,假設你在純 Dos下使用,就會顯示“The program must run under Windows!”

  一個控制臺有三個句柄:標準輸入、標準輸出和和標準錯誤句柄,標準輸入、標準輸出句柄是能夠又一次定向的,你能夠用匿名管道來取代它,這樣一來,你能夠在管道的還有一端用別的進程來接收或輸入,而控制臺一方并沒有感到什么不同,就象 Dos下的 >或者 <能夠又一次定向輸出或輸入一樣。通常控制臺程序的輸入輸出例如以下:

  (控制臺進程output) write ----> 標準輸出設備(通常是屏幕

  (控制臺進程input) read <---- 標準輸入設備(通常是鍵盤)

  而用管道取代后: (作為子進程的控制臺進程output) write ----> 管道1 ----> read (父進程)   (作為子進程的控制臺進程input) read <----> 管道2 <---- write (父進程)
  使用匿名管道的過程例如以下:
  使用CreatePipe建立兩個管道,得到管道句柄,一個用來輸入,一個用來輸出   準備運行控制臺子進程,首先使用GetStartupInfo得到StartupInfo   使用第一個管道句柄取代 StartupInfo中的 hStdInput,第二個取代 hStdOutputhStdError,即標準輸入、輸出、錯誤句柄   使用CreateProcess運行子進程,這樣建立的子進程輸入和輸出就被定向到管道中   父進程通過 ReadFile讀第二個管道來獲得子進程的輸出,通過 WriteFile寫第一個管道來將輸入寫到子進程   父進程能夠通過PeekNamedPipe來查詢子進程有沒有輸出   子進程結束后,要通過CloseHandle來關閉兩個管道。 ?
管道使用的API函數集

CallNamedPipe函數
函數原型:BOOL CallNamedPipe( LPCTSTR lpNamedPipeName, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead, DWORD nTimeOut );
說明這個函數由一個希望通過管道通信的一個客戶進程調用。如有可能,它就同一個管道連接(在必要的情況下等候管道可用)。隨后,它對指定的數據進行讀寫,然后將管道關閉
返回值 :Long,非零表示成功,零表示失敗。會設置GetLastError
參數表 : lpNamedPipeName:LPCTSTR,指定管道名,採用的形式是://./管道/管道名。最多可達256個字符的長度,并且不用區分大寫和小寫。假設存在指定名字的一個管道,則創建那個管道的一個新實例 lpInBuffer:LPVOID,包括了要寫入管道的數據的一個內存緩沖區 nInBufferSize:DWORDlpInBuffer緩沖區中的字符數量 lpOutBufferLPVOID指定一個內存緩沖區,用于裝載從管道中讀出的數據 nOutBufferSizeDWORD指定一個長整數變量,用于裝載來自管道的數據 lpBytesReadLPDWORD指定從管道中讀出的字節數。會閱讀單條消息。如lpOutBuffer的容量不夠大,不能容下整條消息,則函數會返回FALSE,并且GetLastError會設為ERROR_MORE_DATA(消息中留下的不論什么字節都會丟失) nTimeOutDWORD,下列常量之中的一個: 1.???????NMPWAIT_NOWAIT?如管道不可用,則馬上返回一個錯誤 2.???????NMPWAIT_WAIT_FOREVER永遠等候管道可用. 3.???????NMPWAIT_USE_DEFAULT_WAIT:使用管道的默認超時設置,這個設置是用CreateNamedPipe函數指定的
ConnectNamedPipe函數
函數原型:BOOL ConnectNamedPipe( HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped );
說明:指示一臺server等待下去,直至客戶機同一個命名管道連接
返回值:BOOL,如lpOverlappedNULL,那么: 1.????? 如管道已連接,就返回Ture(非零); ????? 如錯誤發生,或者管道已經連接,就返回零(GetLastError此時會返回ERROR_PIPE_CONNECTED 2.????lpOverlapped有效,就返回零; ???????如管道已經連接,GetLastError會返回ERROR_PIPE_CONNECTED ????? 如重疊操作成功完畢,就返回ERROR_IO_PENDING ???????在這兩種情況下,倘若一個客戶已關閉了管道,且server尚未用DisconnectNamedPipe函數同客戶斷開連接,那么GetLastError都會返回ERROR_NO_DATA
參數: hNamedPipeHANDLE,管道的句柄 lpOverlappedLPOVERLAPPED ??????? 如設為NULL(傳遞ByVal As Long),表示將線程掛起,直到一個客戶同管道連接為止。否則就馬上返回; ???? 此時,如管道尚未連接,客戶同管道連接時就會觸發lpOverlapped結構中的事件對象。隨后,可用一個等待函數來監視連接
適用平臺Windows NT
凝視:可用這個函數將一個管道換成同還有一個客戶連接,但首先必須用DisconnectNamedPipe函數斷開同當前進程的連接
CreateNamedPipe函數
函數原型:HANDLE CreateNamedPipe( LPCTSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
說明:創建一個命名管道。返回的句柄由管道的server端使用
返回值:HANDLE,如運行成功,返回管道的句柄。INVALID_HANDLE_VALUE表示失敗.會設置GetLastError
參數: lpNameLPCTSTR,指定管道名,採用的形式是://./管道/管道名。最多可達256個字符的長度,并且不用區分大寫和小寫。假設存在指定名字的一個管道,則創建那個管道的一個新實例 dwOpenModeDWORD下述常數組的一個組合 下述常數之中的一個(對于管道的全部實例都要一樣): 1.?????????PIPE_ACCESS_DUPLEX管道是雙向的 2.?????????PIPE_ACCESS_INBOUND數據從client流到server端 3.?????????PIPE_ACCESS_OUTBOUND數據從server端流到client 下述常數的隨意組合 1.?????????FILE_FLAG_WRITE_THROUGH在網絡中建立的字節型管道內,強迫數據在每次讀寫操作的時候通過網絡傳輸。否則傳輸就可能延遲 2.?????????FILE_FLAG_OVERLAPPED同意(但不要求)用這個管道進行異步(重疊式)操作 常數WRITE_DAC WRITE_OWNER ACCESS_ SYSTEM_SECURITY提供了附加的安全選項 dwPipeModeDWORD,下述常數組的一個組合 下述常數之中的一個(管道的全部實例都必須指定同樣的常數) 1.?????????PIPE_TYPE_BYTE數據作為一個連續的字節數據流寫入管道 2.?????????PIPE_TYPE_MESSAGE數據用數據塊(名為消息報文)的形式寫入管道 下述常數之中的一個: 1.?????????PIPE_READMODE_PIPE數據以單獨字節的形式從管道中讀出 2.?????????PIPE_READMODE_MESSAGE數據以名為消息的數據塊形式從管道中讀出(要求指定PIPE_TYPE_MESSAGE 下述常數之中的一個: 1.?????????PIPE_WAIT同步操作在等待的時候掛起線程 2.?????????PIPE_NOWAIT(不推薦!)同步操作馬上返回。這樣可為異步傳輸提供一種落后的實現方法,已由Win32的重疊式傳輸機制代替了 nMaxInstancesDWORD這個管道可以創建的最大實例數量。必須是1到常數PIPE_UNLIMITED_INSTANCES間的一個值。它對于管道的全部實例來說都應是同樣的 nOutBufferSizeDWORD,建議的輸出緩沖區長度;零表示用默認設置 nInBufferSizeDWORD,建議的輸入緩沖區長度;零表示用默認設置 nDefaultTimeOutDWORD,管道的默認等待超時。對一個管道的全部實例來說都應同樣 lpSecurityAttributesLPSECURITY_ATTRIBUTES,指定一個SECURITY_ATTRIBUTES結構,或者傳遞零值(將參數聲明為ByVal As Long,并傳遞零值),以便使用不同意繼承的一個默認描寫敘述符
適用平臺:Windows NT
CreatePipe函數
函數原型:BOOL CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize );
說明:創建一個匿名管道
返回值:Long,非零表示成功,零表示失敗。會設置GetLastError
參數: phReadPipePHANDLE,指定一個變量,設為管道讀入(輸出)端的一個句柄 phWritePipePHANDLE,指定一個變量,設為管道寫入(輸入)端的一個句柄 lpPipeAttributesLPSECURITY _ATTRIBUTES,指定一個SECURITY_ATTRIBUTES結構,或者傳遞零值,以便使用不同意繼承的一個默認描寫敘述符 nSizeDWORD,管道緩沖區的建議大小。零表示用默認值
注解:匿名管道不同意異步操作,所以如在一個管道中寫入數據,且緩沖區已滿,那么除非還有一個進程從管道中讀出數據,從而騰出了緩沖區的空間,否則寫入函數不會返回
DisconnectNamedPipe函數
函數原型:BOOL DisconnectNamedPipe( HANDLE hNamedPipe );
說明:斷開一個客戶與一個命名管道的連接(server端與client都可調用)
返回值:BOOL,非零表示成功,零表示失敗。會設置GetLastError
參數:hNamedPipe Long,管道的句柄
適用平臺:Windows NT
注解:如客戶尚未在它自己那端關閉管道句柄,下次試圖訪問管道的時候就會錯誤發生
GetNamedPipeHandleState函數
函數原型:BOOL GetNamedPipeHandleState(HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout, LPTSTR lpUserName, DWORD nMaxUserNameSize);
說明:獲取一個命名管道當前的狀態信息
返回值:BOOL,非零表示成功,零表示失敗。會設置GetLastError
參數: hNamedPipe Long,指定一個命名管道的句柄 lpState Long,用于裝載下述一個或多個常數的長整數變量 ???????? PIPE_NOWAIT管道設置成永不阻塞,這樣的模式非常少使用 ???????? PIPE_READMODE_MESSAGE管道設置成讀取消息 lpCurInstancesLong,裝載這個管道眼下存在的實例數量 lpMaxCollectionCount Long,如管道設置成通過一個網絡數據傳輸,就用這個變量裝載通過管道發送之前可排隊等候的最大數據量 lpCollectDataTimeout Long,如管道設置成通過一個網絡數據傳輸,就在這里指定一個長整數變量,用它裝載進行一次網絡數據傳輸前須要等候的最長時間 lpUserName String,如這是個server句柄,就在這里指定一個字串緩沖區,在當中加載客戶應用程序的username。可設為vbNullString,表示不取回信息 nMaxUserNameSize Long,指定lpUserName緩沖區的長度,能夠為零
GetNamedPipeInfo函數
函數原型BOOL GetNamedPipeInfo(HANDLE hNamedPipe,????? LPDWORD lpFlags, LPDWORD lpOutBufferSize, LPDWORD lpInBufferSize, LPDWORD lpMaxInstances);
說明:獲得指定命名管道的信息
返回值:假設函數運行成功,返回值非零,否則,返回值為零,此時調用GetLastError函數獲得擴展錯誤信息
參數 hNamedPipe:命名管道句柄。這個句柄具有命名管道的GENERIC_READ訪問權限。 lpFlags:指定一個識別命名管道類型的32位變量。假設這個信息不需獲得,能夠給此參數置NULL。否則使用下面的值: 1.???????PIPE_CLIENT_END這個句柄是關于一個命名管道的client,此值被默認 2.???????PIPE_SERVER_END 這個句柄是關于命名管道的server端。假設這個值沒有被指定,這個命名管道句柄是關于client的 3.???????PIPE_TYPE_BYTE 命名管道是一個字節管道型,此值被默認 4.??????? PIPE_TYPE_MESSAGE 命名管道是一個消息管道。假設這個值沒有被指定,則默覺得字節管道型 lpOutBufferSize:一個32變量地址。用來按字節,返回輸出數據緩沖的尺寸。假設緩沖值為零,則這個緩沖區沒有按要求分配。假設鎮魂歌信息不須要的,能夠被置NULL. lpInBufferSize:一個32變量地址。用來按字節,返回輸入數據緩沖的尺寸。假設緩沖值為零,則這個緩沖區沒有按要求分配。假設這個信息不須要的,能夠被置NULL. lpMaxInstances:一個32變量地址。用來獲得被創建的管道實例的最大尺寸。假設此位被設置為PIPE_UNLIMITED_INSTANCES,被創建的管道實例的最大尺寸被依照系統的可容量所限制。假設這個信息不須要的,能夠被置NULL.
PeekNamedPipe函數
函數原型:BOOL PeekNamedPipe(HANDLE hNamedPipe, LPVOID lpBuffer,DWORD nBufferSize, LPDWORD lpBytesRead, LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage );
說明:?預覽一個管道中的數據,或取得與管道中的數據有關的信息
返回值: ?BOOL,非零表示成功,零表示失敗。會設置GetLastError
參數: hNamedPipe ?HANDLE,指定一個管道的句柄。這并不一定是某個命名管道的句柄——匿名管道相同適用 lpBuffer ?LPVOID,指定要裝載數據的一個緩沖區的頭一個字符。能夠為零 nBufferSize ?DWORDlpBuffer緩沖區長度 lpBytesRead?LPDWORD,保存裝載到緩沖區的字符數量 lpTotalBytesAvail LPDWORD,保存管道中可用的字符數量 lpBytesLeftThisMessage Long,保存這次讀操作后仍然保留在消息中的字符數。僅僅能為那些基于消息的命名管道設置
注解:由這個函數讀入的數據實際并不能從管道中刪除。假設要對一個管道進行輪詢,了解是否有可能數據,那么使用這個函數特別理想
SetNamedPipeHandleState函數
函數原型: BOOL SetNamedPipeHandleState(HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout );
說明:設置與一個命名管道的運作有關的信息
返回值值:  BOOL,非零表示成功,零表示失敗。會設置GetLastError
參數: hNamedPipe  HANDLE,指定一個命名管道的句柄 lpMode LPDWORD,下列常數的一個或多個:PIPE_WAIT PIPE_NOWAIT PIPE_READMODE_BYTE以及 PIPE_READMODE_MESSAGE。請參考CreateNamedPipe函數,了解有關這些標志的進一步情況 pMaxCollectionCount  LPDWORD,如管道設為通過一個網絡數據傳輸,則在這里指定通過管道發送之前可排除等候的最大數據量 lpCollectDataTimeout  LPDWORD,如管道設為通過一個網絡數據傳輸,則在這里指定網絡數據傳輸前可以忍受的最長等候時間(超時)
TransactNamedPipe函數
函數原型: BOOL TransactNamedPipe( HANDLE hNamedPipe, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped );
說明: 該函數在單獨一個函數中同一時候合并了對管道的讀、寫操作。客戶和server進程都可用它
返回值:  BOOL,如操作已結束,則返回TRUE(非零);否則返回零。在異步模式中,GetLastError會設置成ERROR_IO_PENDING,并且操作會繼續在后臺進行。可測試lpOverlapped結構中的事件對象,了解操作是否結束
參數 hNamedPipe  HANDLE,指定一個消息類型的命名管道的句柄 lpInBuffer LPVOID,指定一個內存緩沖區,在當中包括要寫入管道的數據 nInBufferSize DWORD,指定lpInBuffer緩沖區中的字節數量 lpOutBuffer  LPVOID,指定一個內存緩沖區,用于裝載從管道中讀入的數據 nOutBufferSize  DWORD,用于裝載來自管道的數據 lpBytesRead  LPDWORD,指定要從管道讀入的字節數量。會讀入單條消息。如因為lpOutBuffer不夠大,不能容下完整的消息,那么函數會返回FALSE,并且GetLastError會設為ERROR_MORE_DATA(消息中剩下的全部字節都會丟失) lpOverlapped  LPOVERLAPPED,能夠為NULL(變成ByVal As Long,并傳遞零值),或指定包括了一個事件對象的OVERLAPPED結構
注解:lpOverlapped設為NULL,或者句柄沒有創建成FILE_FLAG_OVERLAPPED樣式,那么除非讀和寫操作都完畢,否則函數不會返回
WaitNamedPipe函數
函數原型: BOOL WaitNamedPipe(LPCTSTR lpNamedPipeName, DWORD nTimeOut );
說明:一個客戶進程調用,等候一個管道變成可用狀態(比方server已調用ConnectNamedPipe函數同一個客戶連接)
返回值:BOOL,非零表示成功;假設失敗,或者管道不存在,則返回零。會設置GetLastError
參數: lpNamedPipeName ?LPCTSTR,指定要連接的管道名稱 nTimeOut ?DWORD,以毫秒數表示的等待時間,或者下述常數之中的一個: 1.????? NMPWAIT_USE_DEFAULT_WAIT使用管道創建時的默認超時設定 2.????NMPWAIT_WAIT_FOREVER永遠等待
注解: 在這個函數之后,用CreateFile打開管道。注意從這個函數返回到調用CreateFile函數期間,倘若有還有一個進程同管道連接,那么這個CreateFile調用可能失敗

?

二、

?

BOOL WaitNamedPipe(   LPCTSTR lpNamedPipeName,   DWORD nTimeOut   );


?

?lpNamedPipeName 要打開的管道名,格式\\servername\pipe\pipename,假設是本地管道則servername能夠使用點“.”。

nTimeOut 等待命名管道的一個實例有效的超時時間,單位毫秒,也能夠使用以下兩個值中的一個:

  ?? NMPWAIT_USE_DEFAULT_WAIT 0x00000000,使用服務端CreateNamedPipe 創建管道時設置的超時時間。

  ?? NMPWAIT_WAIT_FOREVER 0xffffffff,一直等到一個命名管道的實例有效才返回。

返回值:

  假設在超時時間前管道的一個實例有效,返回非0。

  假設超時時間內沒有一個有效的實例,返回0。

注意:

  假設指定的命名管道沒有實例存在,即沒有服務端創建該命名管道(所以在確定server端創建了該命名管道時能夠不調用此API)函數無視超時等待時間直接返回0

  假設函數運行成功返回TRUE,表示至少有一個命名管道的實例有效,接下來應該使用CreateFile函數打開命名管道的一個句柄,可是CreateFile可能會打開管道失敗,由于該實例有可能被服務端關閉或被已經被其它client打開。

?


三、管道使用的傷痛所在

平時都使用得好好的管道突然出發問題了 static inline BOOL CTPipe_WriteNBytes(HANDLE hPipe, BYTE *buf, DWORD size, DWORD timeout, HANDLE stopEvent) {BOOL ret = FALSE;BOOL writeRet;OVERLAPPED ol;BYTE *pos;DWORD cbBytesWrite;HANDLE hWriteEvent;memset( &ol, 0, sizeof(ol) );ol.hEvent = hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);if ( ol.hEvent == NULL ){return FALSE;}pos = buf;while ( size > 0 ){writeRet = WriteFile(hPipe, pos,size,&cbBytesWrite,&ol);if ( writeRet ){pos += cbBytesWrite;size -= cbBytesWrite;ResetEvent(hWriteEvent);}else{if ( GetLastError() == ERROR_IO_PENDING ){DWORD waitRet;HANDLE handles[2];int numOfHandles = 1;handles[0] = hWriteEvent;if ( stopEvent ){handles[1] = stopEvent;numOfHandles++;}waitRet = WaitForMultipleObjects(numOfHandles, handles, FALSE, timeout);if ( waitRet == WAIT_OBJECT_0 ){writeRet = GetOverlappedResult(hPipe, &ol, &cbBytesWrite, TRUE );if ( writeRet == FALSE ){goto EXIT;}pos += cbBytesWrite;size -= cbBytesWrite;ResetEvent(hWriteEvent);}else /* timeout, notify event or other */{/** Cancel request*/if ( CancelIo(hPipe) == FALSE ){L_ERROR(_T("IoCancel fail 0x%x, force close pipe\n"), GetLastError());CloseHandle(hPipe);}else{/** Wait cannel finish*/GetOverlappedResult(hPipe, &ol, &cbBytesWrite, TRUE);}goto EXIT;}}else{goto EXIT;}}}ret = TRUE;EXIT:if ( hWriteEvent ){CloseHandle(hWriteEvent);}return ret; } 在waitRet = WaitForMultipleObjects(numOfHandles, handles, FALSE, timeout);發生了堵塞,此管理是採用異步的,這里寫的管道是作為服務端,問題是服務端的代碼根本就沒有變,倒是管道client的代碼變了。 在client是起一個線程不斷地讀管道的數據,可是讀到數據后是有一個處理數據的過程。 而在曾經的版本號呻這個過程僅僅是PostMessage一個消息,就繼續去ReadFile了;而在新的版本號中讀到數據卻是花了非常多時間去處理數據,然后才去ReadFile。 導致服務端管道寫堵塞的原因:
我們設置的模式是PIPE_WAIT,依據MSDN的要求是:當一端在寫時,還有一要發生讀的動作,才干寫成功;否則堵塞。 hPipe = CreateNamedPipe("Name",PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,PIPE_UNLIMITED_INSTANCES,0,0,0, /*XENHANCE_PIPE_TIMEOUT*/&sa);

解決方法 :
法一、在服務端的管道寫時設置超時時間,這盡管能使用服務端管道的線程不卡死,但也可能該寫的數據沒有寫進去。 法二、依據上圖所看到的,去掉“管道Client端“中的”等待RetEvent事件。 缺點:“管道Client端“不知道自己要求”管道Service端“運行的動作的結果。

1、

2、

3、

4、

5、

6、

7、

轉載于:https://www.cnblogs.com/zfyouxi/p/4210098.html

總結

以上是生活随笔為你收集整理的管道实现进程间通讯 、WaitNamedPipe的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。