一、命名管道(Named Pipes)
管道(Pipe)實際是用於進程間通信的一段共享內存,創建管道的進程稱爲管道服務器,連接到一個管道的進程爲管道客戶機。一個進程在向管道寫入數據後,另一進程就可以從管道的另一端將其讀取出來。
匿名管道(Anonymous Pipes)是在父進程和子進程間單向傳輸數據的一種未命名的管道,只能在本地計算機中使用,而不可用於網絡間的通信。
命名管道,顧名思義,這個管道肯定是有名字的。通過管道的名字來確保多個進程訪問同一個管道。事實上,命名管道不僅可在同一臺計算機的不同進程之間傳輸數據,甚至能在跨越一個網絡的不同計算機的不同進程之間,支持可靠的、單向或雙向的數據通信。
重要函數
CreateNamedPipe
函數功能:創建命名管道
HANDLEWINAPICreateNamedPipe(
LPCTSTRlpName,
DWORDdwOpenMode,
DWORDdwPipeMode,
DWORDnMaxInstances,
DWORDnOutBufferSize,
DWORDnInBufferSize,
DWORDnDefaultTimeOut,
LPSECURITY_ATTRIBUTESlpSecurityAttributes
);
ConnectNamedPipe
函數功能:等待客戶端連接命名管道
函數原型:
BOOLWINAPIConnectNamedPipe(
HANDLEhNamedPipe,
LPOVERLAPPEDlpOverlapped
);
WaitNamedPipe
函數功能:客戶端連接命名管道
函數原型:
BOOLWINAPIWaitNamedPipe(
LPCTSTRlpNamedPipeName,
DWORDnTimeOut
);
二、實例
下面給出使用命名管道的實例,該實例分爲命名管道的服務端和客戶端。服務端和客戶端的主要步驟如下所示:
1. 服務端用CreateNamedPipe創建一個命名管道並使用ConnectNamedPipe等待客戶端的連接
2. 客戶端使用WaitNamedPipe連接成功後,用CreateFile打開管道
3、服務端使用WriteFile向管道中寫入一段數據(即向客戶端發送消息)
4、客戶端使用ReadFile從管道中讀取數據,顯示,調用CloseHandle關閉管道(該管道是CreateFile打開的)。
5、服務端使用DisconnectNamedPipe和CloseHandle關閉管道。
服務端代碼
#include <iostream>
#include <windows.h>
#include <ctime>
using namespace std;
int main()
{
printf("創建命名管道並等待連接\n");
HANDLE hPipe = CreateNamedPipe(L"\\\\.\\Pipe\\mypipe", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT
, PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_WAIT_FOREVER, 0);
//waiting to be connected
if (ConnectNamedPipe(hPipe, NULL) != NULL)
{
printf("連接成功,開始發送數據\n");
DWORD dwWrite;
const char *pStr = "data from server";
if (!WriteFile(hPipe, pStr, strlen(pStr), &dwWrite, NULL))
{
cout << "write failed..." << endl << endl;
return 0;
}
cout << "sent data: " << endl << pStr << endl << endl;
}
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);//關閉管道
printf("關閉管道\n");
system("pause");
}
客戶端代碼
// ClientPip.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//
#include <iostream>
#include <windows.h>
#include <ctime>
#include <conio.h>
using namespace std;
#define BUFSIZE 5
int main()
{
printf("命名管道:客戶端上線\n");
printf("按任意鍵以開始連接命名管道\n");
_getch();
printf("開始等待命名管道\n");
if (WaitNamedPipe(L"\\\\.\\Pipe\\mypipe", NMPWAIT_WAIT_FOREVER) == FALSE)
return 0;
printf("打開命名管道\n");
HANDLE hPipe = CreateFile(L"\\\\.\\Pipe\\mypipe", GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if ((long)hPipe == -1)
return 0;
//接收服務端發回的數據
BOOL fSuccess = false;
DWORD len = 0;
char buffer[BUFSIZE];
string recvData = "";
do
{
fSuccess = ReadFile(hPipe, buffer, BUFSIZE * sizeof(char), &len, NULL);
char buffer2[BUFSIZE + 1] = { 0 };
memcpy(buffer2, buffer, len);
recvData.append(buffer2);
if (!fSuccess || len < BUFSIZE)
break;
} while (true);
cout << "recv data:" << endl << recvData.c_str() << endl << endl;
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
system("pause");
return 0;
}
先打開服務器,再打開客戶端
參考: