1. 程式人生 > >C++ 程序間的通訊 : 簡單的有名管道實現

C++ 程序間的通訊 : 簡單的有名管道實現


一 、管道簡介

命名管道(Named Pipe)是伺服器程序和一個或多個客戶程序之間通訊的單向或雙向管道。不同於匿名管道的是命名管道可以在不相關的程序之間和不同計算機之間使用,伺服器建立命名管道時給它指定一個名字,任何程序都可以通過該名字開啟管道的另一端,根據給定的許可權和伺服器程序通訊。

其優點是實現起來比較簡單方便 .

缺點是會使程序之間的程式碼耦合度增加.並且管道通訊只適用於同一臺主機上的程序之間通訊.

二 、實現程式碼

Server Code:

#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <ctime>
 
int main(int argc, _TCHAR* argv[])
{
	srand(time(NULL));
 
	char buf[256] = "";
	DWORD rlen = 0;
	HANDLE hPipe = CreateNamedPipe(
		TEXT("\\\\.\\Pipe\\mypipe"),						//管道名
		PIPE_ACCESS_DUPLEX,									//管道型別 
		PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT,	//管道引數
		PIPE_UNLIMITED_INSTANCES,							//管道能建立的最大例項數量
		0,													//輸出緩衝區長度 0表示預設
		0,													//輸入緩衝區長度 0表示預設
		NMPWAIT_WAIT_FOREVER,								//超時時間
		NULL);													//指定一個SECURITY_ATTRIBUTES結構,或者傳遞零值.
	if (INVALID_HANDLE_VALUE == hPipe)
	{
		printf("Create Pipe Error(%d)\n",GetLastError());
	}
	else
	{
		printf("Waiting For Client Connection...\n");
		if(ConnectNamedPipe(hPipe, NULL)==NULL)	//阻塞等待客戶端連線。
		{
			printf("Connection failed!\n");
		}
		else
		{
			printf("Connection Success!\n");
		}
 
		while (true)
		{
			if(ReadFile(hPipe,buf,256,&rlen,NULL)==FALSE) //接受客戶端傳送過來的內容
			{			
				printf("Read Data From Pipe Failed!\n");
				break;
			}
			else
			{
				printf("From Client: data = %s, size = %d\n", buf, rlen);
				char wbuf[256] = "";
				sprintf(wbuf, "%s%d", wbuf, rand()%1000);
				DWORD wlen = 0;
				WriteFile(hPipe, wbuf, sizeof(wbuf), &wlen, 0);	//向客戶端傳送內容
				printf("To Client: data = %s, size = %d\n", wbuf, wlen);
				Sleep(1000);
			}
		}
		CloseHandle(hPipe);//關閉管道
	}
 
	system("PAUSE");
	return 0;
}

Clietn Code:

#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <ctime>
 
int main(int argc, _TCHAR* argv[])
{
	srand(time(NULL));
 
	DWORD wlen = 0;
	Sleep(1000);//等待pipe的建立成功!
 
	BOOL bRet = WaitNamedPipe(TEXT("\\\\.\\Pipe\\mypipe"), NMPWAIT_WAIT_FOREVER);
 
	if (!bRet)
	{
		printf("connect the namedPipe failed!\n");
		return 0;
	}
 
	HANDLE hPipe=CreateFile(			//管道屬於一種特殊的檔案
		TEXT("\\\\.\\Pipe\\mypipe"),	//建立的檔名
		GENERIC_READ | GENERIC_WRITE,	//檔案模式
		0,								//是否共享
		NULL,							//指向一個SECURITY_ATTRIBUTES結構的指標
		OPEN_EXISTING,					//建立引數
		FILE_ATTRIBUTE_NORMAL,			//檔案屬性(隱藏,只讀)NORMAL為預設屬性
		NULL);							//模板建立檔案的控制代碼
 
	if (INVALID_HANDLE_VALUE == hPipe)
	{
		printf("open the exit pipe failed!\n");
	}
	else
	{
		while(true)
		{
			char buf[256] = "";
			sprintf(buf,"%s%d",buf,rand()%1000);
			if(WriteFile(hPipe,buf,sizeof(buf),&wlen,0)==FALSE)	//向伺服器傳送內容
			{
				printf("write to pipe failed!\n");
				break;
			}
			else
			{
				printf("To Server: data = %s, size = %d\n", buf, wlen);
				char rbuf[256] = "";
				DWORD rlen = 0;
				ReadFile(hPipe, rbuf, sizeof(rbuf), &rlen, 0);	//接受服務傳送過來的內容
				printf("From Server: data = %s, size = %d\n", rbuf, rlen);
			}
			Sleep(1000);
		}
		CloseHandle(hPipe);//關閉管道
	}
 
	system("PAUSE");
	return 0;
}