C 和C 程序間通過命名管道來通訊(附原始碼) 上

2021-04-18 10:08:54 字數 3945 閱讀 2068

c++和c#程序之間通過命名管道通訊(上)

「命名管道」是一種簡單的程序間通訊(ipc)機制。命名管道可在同一臺計算機的不同程序之間,或在跨越乙個網路的不同計算機的不同程序之間,支援可靠的、單向或雙向的資料通訊。用命名管道來設計應用程式實際非常簡單,並不需要事先深入掌握基層網路傳送協議(如tcp/ip或ipx)的知識。因為命名管道利用了微軟網路提供者(msnp)重定向器,通過乙個網路,在各程序間建立通訊。這樣一來,應用程式便不必關心網路協議的細節。

命令管道是圍繞windows檔案系統設計的一種機制,採用「命名管道檔案系統」(namedpipefilesystem,npfs)介面。因此,客戶機和伺服器應用可利用標準的win32檔案系統api函式(如readfile和writefile)來進行資料的收發。通過這些api函式,應用程式便可直接利用win32檔案系統命名規範,以及windowsnt/windows2000檔案系統的安全機制。npfs依賴於msnp重定向器在網上進行命名管道資料的傳送和接收。這樣一來,便可實現介面的「與協議無關」特性:若在自己開發的應用程式中使用命名管道在網上不同的程序間建立通訊,程式設計師不必關心基層網路傳送協議(如tcp和ipx等等)的細節。

客戶機和伺服器

命名管道最大的特點便是建立乙個簡單的客戶機/伺服器程式設計體系。在這個體系結構中,在客戶機與伺服器之間,資料既可單向傳遞,亦可雙向流動。對命名管道伺服器和客戶機來說,兩者的區別在於:伺服器是唯一乙個有權建立命名管道的程序,也只有它才能接受管道客戶機的連線請求。對乙個客戶機應用來說,它只能同乙個現成的命名管道伺服器建立連線。在客戶機應用和伺服器應用之間,一旦建好連線,兩個程序都能對標準的win32函式,在管道上進行資料的讀取與寫入。這些函式包括readfile和writefile等等。

伺服器

要想實現乙個命名管道伺服器,要求必須開發乙個應用程式,通過它建立命名管道的乙個或多個「例項」,再由客戶機進行訪問。對伺服器來說,管道例項實際就是乙個控制代碼,用於從本地或遠端客戶機應用接受乙個連線請求。按下述步驟行事,便可寫出乙個最基本的伺服器應用:

1)使用api函式createnamedpipe,建立乙個命名管道例項控制代碼。

2)使用api函式connectnamedpipe,在命名管道例項上監聽客戶機連線請求。

3)使用api函式readfile,從客戶機接收資料;使用api函式writefile,將資料發給客戶機。

4)使用api函式disconnectnamedpipe,關閉命名管道連線。

5)使用api函式closehandle,關閉命名管道例項控制代碼。

首先,我們的伺服器程序需要使用createnamedpipe這個api呼叫,建立乙個命名管道例項。

下面給出createnamedpipe()的函式原型:

handle createnamedpipe(

lpctstr lpname,//指向管道名稱的指標

dword dwopenmode,//管道開啟模式

dword dwpipemode,//管道模式

dword nmaxinstances,//最大例項數

dword noutbuffersize,//輸出快取大小

dword ninbuffersize,//輸入快取大小

dword ndefaulttimeout,//超時設定

lpsecurity_attributes lpsecurityattributes//安全屬性指標

);

其中幾個主要引數如下:

lpname

是管道的名稱,命名管道的命名採用如下格式:

//servername/pipe/pipename

其中,第一部分//servername指定了伺服器的名字,命名管道服務即在此伺服器建立,而且要由它對進入的連線請求進行「監聽」,其字串部分可表示為乙個小數點」.」(表示本機)、星號(當前網路字段)、網域名稱或是乙個真正的服務;第二部分/pipe是乙個不可變化的硬編碼字串,以指出該檔案是從屬於npfs,不區分大小寫;第三部分/pipename則是應用程式可以唯一定義及標識乙個命名管道的名字,而且可以設定多級目錄。

dwopenmode

引數用於指示乙個管道建立好之後,它的傳輸方向、i/o控制以及安全模式。pipe_access_標誌決定了在客戶機與伺服器之間,資料在管道上的流動方向。可用pipe _access_duplex標誌以雙向傳輸方式開啟乙個管道。也就是說,在客戶機與伺服器之間,資料可以雙向傳輸。除此以外,亦可使用pipe_access_inbound或者pipe_access_outbound標誌,以單向傳輸方式開啟乙個管道。也就是說,資料只能從客戶機傳向伺服器,或從伺服器傳向客戶機。

dwpipemod

命名管道提供了兩種基本的通訊模式:位元組模式(pipe_type_byte)和訊息模式(pipe_type_message)。在位元組模式中,資訊以連續位元組流的形式在客戶與伺服器之間流動,這也就意味著,對於客戶機應用和伺服器應用,在任何乙個特定的時間段內,都無法準確知道有多少位元組從管道中讀出或寫入。在這種通訊模式中,一方在向管道寫入某個數量的位元組後,並不能保證管道另一方能讀出等量的位元組。對於訊息模式,客戶機和伺服器則是通過一系列不連續的資料報進行資料的收發。從管道發出的每一條訊息都必須作為一條完整的訊息讀入。

其他的函式及其引數含義詳見msdn,此處不一一講解。

伺服器呼叫該函式,如果在已定義超時值變為零以前,有乙個例項管道可以使用,則建立成功並返回管道控制代碼,以此偵聽來自客戶機的連線請求。

客戶機

實現乙個命名管道客戶機時,要求開發乙個應用程式,令其建立與某個命名管道伺服器的連線。注意客戶機不可建立命名管道例項。然而,客戶機可開啟來自伺服器的、現成的例項。下述步驟講解了如何編寫乙個基本的客戶機應用:

1)用api函式waitnamedpipe,等候乙個命名管道例項可供自己使用。

2)用api函式createfile,建立與命名管道的連線。

3)用api函式writefile和readfile,分別向伺服器傳送資料,或從中接收資料。

4)用api函式closehandle,關閉開啟的命名管道會話。

建立乙個連線之前,客戶機需要用waitnamedpipe函式,檢查是否存在乙個現成的命名管道例項。waitnamedpipe成功完成後,客戶機需要用createfile這個api函式,開啟指向伺服器命名管道例項的乙個控制代碼。

簡單說來,伺服器呼叫createnamedpipe來建立管道,如果在已定義超時值變為零以前,有乙個例項管道可以使用,則建立成功並返回管道控制代碼,以此偵聽來自客戶機的連線請求。另一方面,客戶機通過函式waitnamedpipe()使伺服器程序等待來自客戶的例項連線。如果在超時值變為零以前,有乙個管道可供連線使用,則函式將成功返回,並通過呼叫createfile()或callnamedpipe()來呼叫對伺服器的連線。此時伺服器將接受客戶的連線請求,成功建立連線,伺服器呼叫的等待客戶機建立連線的connectnamedpipe()函式也將成功返回。然後,管道兩端就可以進行通訊了。

從呼叫時序上看,首先是客戶機通過waitnamedpipe()使伺服器的createfile()在限時時間內建立例項成功,然後雙方通過connectnamedpipe()和createfile()成功連線,在返回用以通訊的檔案控制代碼後,客戶、服務雙方即可進行通訊。

在建立了連線後,客戶機與伺服器即可通過readfile()和writefile()並利用得到的管道控制代碼,以檔案讀寫的形式彼此間進行資訊交換。當客戶與伺服器的通訊結束,或是由於某種原因一方需要斷開時,由客戶機呼叫closefile()函式關閉開啟的管道控制代碼,伺服器隨即呼叫disconnectnamedpipe()函式。當然,伺服器也可以通過單方面呼叫disconnectnamedpipe()來終止連線。在終止連線後呼叫函式closehandle()來關閉此管道。

下篇將給出的程式清單即是按照上述方法實現的命名管道伺服器和客戶機進行通訊的程式實現**:

程序間通訊 命名管道

程序間通訊的本質是不同的程序看到了同乙份公共的資源。而管道的 乙個不 足之處是沒有名字,因此,只能 用於具有親緣關係的程序間通訊,在命名管道 named pipe或fifo 提出後,該限制得到了克服。fifo不同於管道之處在於它提供 乙個路徑名與之關聯,以fifo的 檔案形式儲存於 檔案系統中。命名...

程序間通訊 命名管道

命名管道,和匿名管道,有了自己的名字,有了名字就可以操作。所以他不在侷限於有血緣關係的兩個程序之間,適用於任意的兩個程序。實際上和匿名管道一樣是一塊核心中的快取,和匿名管道不一樣的是,他在檔案系統中多了檔案,而匿名管道的檔案只存在與記憶體中,但是命名管道的檔案雖然存在,有在核心資料結構中有自己的環境...

程序間通訊 命名管道

命名管道 命名管道是乙個存在於檔案系統的乙個特殊檔案,命名管道和匿名管道區別 建立命名管道 從命令列建立 mkfifo filename 在程式中建立 函式原型 int mkfifo const char filename,mode t mode 返回值 成功返回 如果檔案已經存在返回 errno為...