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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[转载]使用命名管道实现进程间通信

發(fā)布時間:2023/11/29 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转载]使用命名管道实现进程间通信 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
使用命名管道實現(xiàn)進(jìn)程間通信
來源 : VChelp

4.5 進(jìn)程間通信

在Win32下提供的進(jìn)程間通信方式有以下幾種:

剪貼板Clipboard:在16位時代常使用的方式,CWnd類中提供了支持。
COM/DCOM:通過COM系統(tǒng)的代理存根方式進(jìn)行進(jìn)程間數(shù)據(jù)交換,但只能夠表現(xiàn)在對接口函數(shù)的調(diào)用時傳送數(shù)據(jù),通過DCOM可以在不同主機(jī)間傳送數(shù)據(jù)。
Dynamic Data Exchange (DDE):在16位時代常使用的方式。
File Mapping:文件映射,在32位系統(tǒng)中提供的新方法,可用來共享內(nèi)存。
Mailslots:郵件槽,在32位系統(tǒng)中提供的新方法,可在不同主機(jī)間交換數(shù)據(jù),分為服務(wù)器方和客戶方,雙方可以通過其進(jìn)行數(shù)據(jù)交換,在Win9X下只支持郵件槽客戶。
Pipes:管道,分為無名管道:在父子進(jìn)程間交換數(shù)據(jù);有名管道:可在不同主機(jī)間交換數(shù)據(jù),分為服務(wù)器方和客戶方,在Win9X下只支持有名管道客戶。
RPC:遠(yuǎn)程過程調(diào)用,很少使用,原因有兩個:復(fù)雜而且與UNIX系統(tǒng)的RCP并不完全兼容。但COM/DCOM的調(diào)用是建立在RPC的基礎(chǔ)上的。
Windows Sockets:網(wǎng)絡(luò)套接口,可在不同主機(jī)間交換數(shù)據(jù),分為服務(wù)器方和客戶方。(相關(guān)介紹見Visual C++/MFC入門教程 第六章 網(wǎng)絡(luò)通信開發(fā))
WM_COPYDATA:通過發(fā)送WM_COPYDATA消息并將數(shù)據(jù)放在參數(shù)中來傳遞數(shù)據(jù)給其他進(jìn)程。
下面主要介紹一下命名管道的用法,命名管道是一個有名字,單向或雙向的通信管道。管道的名稱有兩部分組成:計算機(jī)名和管道名,例如\\[host_name]\pipe\[pipe_name]\(括號內(nèi)為參數(shù))。對于同一主機(jī)來講允許有多個同一命名管道的實例并且可以由不同的進(jìn)程打開,但是不同的管道都有屬于自己的管道緩沖區(qū)而且有自己的通訊環(huán)境互不影響,并且命名管道可以支持多個客戶端連接一個服務(wù)器端。命名管道客戶端不但可以與本機(jī)上的服務(wù)器通訊也可以同其他主機(jī)上的服務(wù)器通訊。

命名管道的連接和通訊采用如下方式:

在服務(wù)器端第一次創(chuàng)建命名管道后等待連接,當(dāng)客戶端連接成功后服務(wù)器端的命名管道就用作通訊用途。如果需要再次等待連接,服務(wù)器端就需要再次打開命名管道(創(chuàng)建一個命名管道的實例)并等待連接。
對于客戶端每次打開命名管道后建立與服務(wù)器間的連接,然后就可以利用命名管道進(jìn)行通信,如果需要建立第二個連接則需要再次打開管道和再次建立連接。
創(chuàng)建命名管道時需要指定一個主機(jī)名和管道名,對于客戶端來說可以是如下格式:\\[host_name]\pipe\[pipe_name]\也可以是\\.\pipe\pipe_name\其中.表示本機(jī)。而服務(wù)器端只能夠在指定本機(jī)作為主機(jī)名,即只能使用下面的格式:\\.\pipe_name\。此外需要記住,在同一主機(jī)上管道名稱是唯一的,一個命名管道一旦被創(chuàng)建就不允許相同名稱的管道再被創(chuàng)建。

服務(wù)器方通過:

HANDLE CreateNamedPipe(
??LPCTSTR lpName,???????????????????????????? // pipe name
??DWORD dwOpenMode,?????????????????????????? // pipe open mode
??DWORD dwPipeMode,?????????????????????????? // pipe-specific modes
??DWORD nMaxInstances,????????????????????????// maximum number of instances
??DWORD nOutBufferSize,?????????????????????? // output buffer size
??DWORD nInBufferSize,????????????????????????// input buffer size
??DWORD nDefaultTimeOut,??????????????????????// time-out interval
??LPSECURITY_ATTRIBUTES lpSecurityAttributes??// SD
);
創(chuàng)建命名管道和打開已經(jīng)存在的命名管道,其中l(wèi)pName為管道名稱,dwOpenMode為創(chuàng)建方式,可以是下面值的組合:
PIPE_ACCESS_INBOUND:管道只能用作接收數(shù)據(jù)。
PIPE_ACCESS_OUTBOUND:管道只能用作發(fā)送數(shù)據(jù)。
PIPE_ACCESS_DUPLEX:管道既可以發(fā)送也可以接收數(shù)據(jù)。(上面這三個值只能夠取其中一個)
FILE_FLAG_WRITE_THROUGH:管道用于同步發(fā)送和接收數(shù)據(jù),只有在數(shù)據(jù)被發(fā)送到目標(biāo)地址時發(fā)送函數(shù)才會返回,如果不設(shè)置這個參數(shù)那么在系統(tǒng)內(nèi)部對于命名管道的處理上可能會因為減少網(wǎng)絡(luò)附和而在數(shù)據(jù)積累到一定量時才發(fā)送,并且對于發(fā)送函數(shù)的調(diào)用會馬上返回。
FILE_FLAG_OVERLAPPED:管道可以用于異步輸入和輸出,異步讀寫的有關(guān)方法和文件異步讀寫是相同的。
dwPipeMode指定管道類型,可以是下面值的組合:
PIPE_TYPE_BYTE:數(shù)據(jù)在通過管道發(fā)送時作為字節(jié)流發(fā)送,不能與PIPE_READMODE_MESSAGE共用。
PIPE_TYPE_MESSAGE:數(shù)據(jù)在通過管道發(fā)送時作為消息發(fā)送,不能與PIPE_READMODE_BYTE共用。
PIPE_READMODE_BYTE:在接收數(shù)據(jù)時接收字節(jié)流。
PIPE_READMODE_MESSAGE:在接收數(shù)據(jù)時接收消息。
PIPE_WAIT:使用等待模式,在讀,寫和建立連接時都需要管道的另一方完成相應(yīng)動作后才會返回。
PIPE_NOWAIT:使用非等待模式,在讀,寫和建立連接時不需要管道的另一方完成相應(yīng)動作后就會立即返回。
nMaxInstances為管道的的最大數(shù)量,在第一次建立服務(wù)器方管道時這個參數(shù)表明該管道可以同時存在的數(shù)量。PIPE_UNLIMITED_INSTANCES表明不對數(shù)量進(jìn)行限制。nOutBufferSize和nInBufferSize表示緩沖區(qū)的大小。nDefaultTimeOut表示在等待連接時最長的等待時間(以毫秒為單位),如果在創(chuàng)建時設(shè)置為NMPWAIT_USE_DEFAULT_WAIT表明無限制的等待,而以后服務(wù)器方的其他管道實例也需要設(shè)置相同的值。lpSecurityAttributes為安全屬性,一般設(shè)置為NULL。如果創(chuàng)建或打開失敗則返回INVALID_HANDLE_VALUE。可以通過GetLastError得到錯誤。
客戶方通過:

HANDLE CreateFile(
??LPCTSTR lpFileName,???????????????????????? // file name
??DWORD dwDesiredAccess,??????????????????????// access mode
??DWORD dwShareMode,??????????????????????????// share mode
??LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD
??DWORD dwCreationDisposition,????????????????// how to create
??DWORD dwFlagsAndAttributes,???????????????? // file attributes
??HANDLE hTemplateFile????????????????????????// handle to template file
);
創(chuàng)建客戶端命名管道,CreateFile可以有很多用途,可以用來創(chuàng)建文件,管道,郵件槽,目錄等,這里介紹用CreateFile來打開客戶端命名管道。lpFileName用來指明管道名稱。dwDesiredAccess用來表明使用方式,可以使用下面的值:
GENERIC_READ:打開一個只用于讀的管道。
GENERIC_WRITE:打開一個只用于寫的管道。
GENERIC_READ | GENERIC_WRITE:打開一個用于讀和寫的管道。
dwShareMode指定共享方式,一般指定為0,lpSecurityAttributes為安全屬性,一般設(shè)置為NULL,dwCreationDisposition設(shè)置為OPEN_EXISTING,dwFlagsAndAttributes設(shè)置為FILE_ATTRIBUTE_NORMAL,此外可以還設(shè)置為FILE_FLAG_OVERLAPPED來進(jìn)行異步通訊,hTemplateFile設(shè)置為NULL。如果打開失敗則返回INVALID_HANDLE_VALUE。可以通過GetLastError得到錯誤。
此外客戶方可以利用:

BOOL CallNamedPipe(
??LPCTSTR lpNamedPipeName,??// pipe name
??LPVOID lpInBuffer,????????// write buffer
??DWORD nInBufferSize,??????// size of write buffer
??LPVOID lpOutBuffer,?????? // read buffer
??DWORD nOutBufferSize,???? // size of read buffer
??LPDWORD lpBytesRead,??????// number of bytes read
??DWORD nTimeOut????????????// time-out value
);
來創(chuàng)建一個發(fā)送消息的管道。
管道的連接管理,客戶方在調(diào)用CreateFile后立即就能夠建立服務(wù)器的連接,而服務(wù)器方一旦管道打開或創(chuàng)建后可以用

BOOL ConnectNamedPipe(
??HANDLE hNamedPipe,??????????// handle to named pipe
??LPOVERLAPPED lpOverlapped?? // overlapped structure
);
來等待客戶端的連接建立。如果希望在服務(wù)器方檢測是否有連接到達(dá),可以調(diào)用
BOOL WaitNamedPipe(
??LPCTSTR lpNamedPipeName,??// pipe name
??DWORD nTimeOut????????????// time-out interval
);

這里的lpNamePipeName直接使用創(chuàng)建管道時的名稱,如果在服務(wù)器方希望關(guān)閉連接則調(diào)用
BOOL DisconnectNamedPipe(
??HANDLE hNamedPipe?? // handle to named pipe
);

一旦連接被關(guān)閉,服務(wù)器方可以再次調(diào)用ConnectNamedPipe來建立連接。如果要關(guān)閉管道則直接調(diào)用CloseHandle。請注意這里提到的關(guān)閉管道和關(guān)閉連接是不同的意思,在同一個管道上可以依次反復(fù)建立連接,而且可以減小系統(tǒng)的負(fù)荷。而且如果指定了管道最大數(shù)量限制那么在打開的管道達(dá)到最大限制后如果不關(guān)閉舊管道就無法打開新管道。

對于客戶方則無法關(guān)閉連接,而只能直接調(diào)用CloseHandle關(guān)閉管道。

數(shù)據(jù)的發(fā)送,不論是服務(wù)器還是客戶方都可以通過ReadFile和WriteFile進(jìn)行管道讀寫來達(dá)到通訊的目的。

下面是一個例子,服務(wù)器方創(chuàng)建或打開一個管道并讀入對方發(fā)送的數(shù)據(jù),將小寫字母轉(zhuǎn)換成大寫字母后返回,而客戶發(fā)創(chuàng)建一個到服務(wù)器的連接并發(fā)送一個字符串并讀回經(jīng)過轉(zhuǎn)換的數(shù)據(jù):

在使用這個例子時,運行三個服務(wù)端進(jìn)程,而運行第四個時會因為達(dá)到管道數(shù)量限制而打開管道失敗。

//服務(wù)方
void CNamed_pipeDlg::OnCreateP()
{
????DWORD dwTO = NMPWAIT_USE_DEFAULT_WAIT;//設(shè)置連接等待時間
????HANDLE hSvr = CreateNamedPipe("\\\\.\\pipe\\test_pipe\\",PIPE_ACCESS_DUPLEX,PIPE_TYPE_BYTE,3,256,256,dwTO,NULL);
????if( INVALID_HANDLE_VALUE == hSvr)
????{
????????AfxMessageBox("Error create/open pipe");
????}
????else
????{
????????if (ConnectNamedPipe(hSvr,NULL))
????????{
????????????BYTE bRead;
????????????DWORD dwRead,dwWritten;
????????????while (ReadFile(hSvr,&bRead,1,&dwRead,NULL))
????????????{
????????????????if(bRead >= 'a' && bRead $lt;='z')
????????????????????bRead = 'A'+ (bRead-'a');
????????????????WriteFile(hSvr,&bRead,1,&dwWritten,NULL);
????????????}
????????}
????????else
????????{
????????????AfxMessageBox("error when waiting connected");
????????}
????????CloseHandle(hSvr);
????}
}
//客戶端
void CNamed_pipe_cDlg::OnConn()
{
????HANDLE hClient = CreateFile("\\\\.\\pipe\\test_pipe\\",GENERIC_WRITE |GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
????if(hClient == INVALID_HANDLE_VALUE)
????{
????????AfxMessageBox("Error open pipe");
????}
????else
????{
????????????DWORD dwRead,dwWritten;
????????????char szSend[10]="send...";
????????????char szRecv[10];
????????????for(int i=0;i<strlen(szSend)+1;i++)
????????????{
????????????????WriteFile(hClient,szSend+i,1,&dwWritten,NULL);
????????????????ReadFile(hClient,szRecv+i,1,&dwRead,NULL);
????????????}
????????????CloseHandle(hClient);//close pipe
????????????AfxMessageBox(szRecv);
????}
}

總結(jié)

以上是生活随笔為你收集整理的[转载]使用命名管道实现进程间通信的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。