明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

VC命名管道通信的完成

[摘要]無論是SQL Server的用戶,還是PB的用戶,作為C/S結(jié)構(gòu)開發(fā)環(huán)境,他們在網(wǎng)絡(luò)通信的實現(xiàn)上,都有一種共同的方法——命名管道。由于當前操作系統(tǒng)的不惟一性,各個系統(tǒng)都有其獨自的通信協(xié)議,導致了不同...
無論是SQL Server的用戶,還是PB的用戶,作為C/S結(jié)構(gòu)開發(fā)環(huán)境,他們在網(wǎng)絡(luò)通信的實現(xiàn)上,都有一種共同的方法——命名管道。由于當前操作系統(tǒng)的不惟一性,各個系統(tǒng)都有其獨自的通信協(xié)議,導致了不同系統(tǒng)間通信的困難。盡管TCP/IP協(xié)議目前已發(fā)展成為Internet的標準,但仍不能保證C/S應(yīng)用程序的順利進行。命名管道作為一種通信方法,有其獨特的優(yōu)越性,這主要表現(xiàn)在它不完全依賴于某一種協(xié)議,而是適用于任何協(xié)議——只要能夠?qū)崿F(xiàn)通信。

  命名管道具有很好的使用靈活性,表現(xiàn)在:

  1) 既可用于本地,又可用于網(wǎng)絡(luò)。

  2) 可以通過它的名稱而被引用。

  3) 支持多客戶機連接。

  4) 支持雙向通信。

  5) 支持異步重疊I/O操作。

  不過,當前只有Windows NT支持服務(wù)端的命名管道技術(shù)。



  一、命名管道程序設(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)閉該管道。

  2.命名管道服務(wù)器端和客戶端代碼實現(xiàn)

  (1)客戶端:

  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ù)——從管道讀、寫信息。

  ……

  (2)服務(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ù)

  ……



  二、程序設(shè)計的注意事項

  1.如果命名管道客戶端已打開,函數(shù)將會強迫關(guān)閉管道,用DisconnectNamedPipe關(guān)閉的管道,其客戶端還必須用CloseHandle來關(guān)閉最后的管道。

  2. ReadFile和WriteFile的hFile句柄是由CreateFile及ConnectNamedPipe返回得到。

  3.一個已被某客戶端連接的管道句柄在被另一客戶通過ConnectNamedPipe建立連接之前,服務(wù)端必須用DisconnectNamedPipe函數(shù)對已存在的連接進行強行拆離。服務(wù)端拆離管道會造成管道中數(shù)據(jù)的丟失,用FlushFileBuffers函數(shù)可以保證數(shù)據(jù)不被丟失。

  4.命名管道服務(wù)端可以通過新創(chuàng)建的管道句柄或已被連接過其他客戶的管道句柄來使用ConnectNamedPipe函數(shù),但在連接新的客戶端之前,服務(wù)端必須用函數(shù)DisconnectNamedPipe切斷之前的客戶句柄,否則ConnectNamedPipe 將會返回False。

  5.阻塞模式,這種模式僅對“字節(jié)傳輸管道"操作有效,并且要求客戶端與服務(wù)端不在同一機器上。如果用這種模式,則只有當函數(shù)通過網(wǎng)絡(luò)向遠端計算機管道緩沖器寫數(shù)據(jù)成功時,才能有效返回。如果不用這種模式,系統(tǒng)會運行缺省方式以提高網(wǎng)絡(luò)的工作效率。

  6.用戶必須用FILE—CREATE—PIPE—INSTANCE 來訪問命名管道對象。新的命名管道建立后,來自安全參數(shù)的訪問控制列表定義了訪問該命名管道的權(quán)限。所有命名管道實例必須使用統(tǒng)一的管道傳輸方式、管道模式等參數(shù)?蛻舳宋磫,管道服務(wù)端不能執(zhí)行阻塞讀操作,否則會發(fā)生空等的阻塞狀態(tài)。當最后的命名管道實例的最后一個句柄被關(guān)閉時,就應(yīng)該刪除該命名管道。

  摘自《賽迪網(wǎng)》 冷山述/文