【IPC程式間通訊之二】管道Pipe

Love_Hulidear發表於2014-05-15

IPC程式間通訊+管道Pipe

      
        IPC(Inter-Process Communication,程式間通訊)。
        管道用於程式間共享資料,其實質是共享記憶體,常用IPC之一。管道不僅可以用於本機程式間通訊,還可實現跨網路程式間通訊,如同Socket通訊,管道同樣封裝計算機底層網路實現,提供一個良好的API介面。
       
       1.管道(Pipe)

       管道分為匿名管道和命名管道。
       匿名管道只能用於父子程式間通訊 ,不能跨網路通訊,並且通訊是單向。
       命名管道可用於任意程式間通訊,支援跨網路通訊,並且通訊是雙向,任意一段都可以接收和傳送資料。命名管道是學習的重點。
       命名管道通訊程式分為服務端客戶端,服務端建立Pipe,客戶端通過管道名連線該Pipe之後,雙方均可通過該Pipe傳送和接收資料。
       
        2.郵槽命名 :
       本機上格式:\\ServerName\Pipe\name
       如:\\.\Pipe\my_pipe

       3.基本API函式 :
建立命名管道:
        HANDLE    CreateNamedPipe(
                        LPCTSTR   lpName,                // 指向管道名稱的指標
                        DWORD     dwOpenMode,       // 管道開啟模式
                        DWORD     dwPipeMode,       // 管道模式
                        DWORD     nMaxInstances,     // 最大例項數
                        DWORD     nOutBufferSize,   // 輸出快取大小
                        DWORD     nInBufferSize,       // 輸入快取大小
                        DWORD    nDefaultTimeOut, // 超時設定
LPSECURITY_ATTRIBUTES lpSecurityAttributes   // 安全屬性指標
);
        該函式用於伺服器端建立命名管道。
等待客戶端連線:
        BOOL  ConnectNamedPipe(
                     HANDLE    hNamedPipe,        //管道控制程式碼
                     LPOVERLAPPED   lpOverlapped     //設為NULL
); 
        該函式用於伺服器等待客戶端連線到管道。
檢查命名管道:
        BOOL  WaitNamedPipe(
                     LPCTSTR   lpNamedPipeName,  //管道名
                     DWORD     nTimeOut                  //超時
);
         該函式用於客戶端檢查是否存在管道Pipe。
開啟命名管道:
        BOOL  CreateFile(
                     LPCTSTR   lpFileName,
                     DWORD     dwDesiredAccess,
                     DWORD     dwShareMode,
                     LPSECURITY_ATTRIBUTES   lpSecurityAttributes,
                     DWORD    dwCreationDisposition,
                     DWORD    dwFlagsAndAttributes,
                    HANDLE    hTemplateFile
 
);
         第一個引數:管道名指標。
         第二個引數:訪問模式。
         第三個引數:共享模式。
         第四個引數:安全屬性指標。
         第五個引數:建立選項。
         第六個引數:檔案屬性。
         第七個引數:用於複製檔案控制程式碼。
         該函式用於開啟一個管道,並返回管道控制程式碼。
讀取管道:       
        BOOL ReadFile(
                    
HANDLE    hFile,
                    LPVOID     lpBuffer,
                    DWORD    nNumberOfBytesToRead,
                    LPDOWRD    lpNumberOfBytesRead,
                    LPOVERLAPPED   lpOverlapped
);
        第一個引數:管道控制程式碼。
        第二個引數:快取地址。
        第三個引數:訊息的長度。
        第四個引數:實際讀取的長度。
        第五個引數:一般設定為NULL。
        該函式用於讀取管道內資料。
寫入管道:
        BOOL  WriteFile(
                     HANDLE    hFile,
                     LPCVOID   lpBuffer,
                     DWORD     nNumberOfBytesToWrite,
                     LPDWORD   lpNumberOfBytesWritten,
                     LPOVERLAPPED    lpOverlapped
);
         第一個引數:管道控制程式碼。
         第二個引數:資料緩衝區指標。
         第三個引數:寫入位元組數。
         第四個引數:返回實際寫入位元組數。
         第五個引數:結構體指標,一般置NULL。
         該函式用於客戶端向管道寫入資料。

         4.牛刀小試 : 
         先在VC6.0中執行服務端程式,在執行客戶端程式。

         執行效果:

伺服器程式:
#include
#include

int main()
{
	char Buffer[10000];
	DWORD ReadNum;

	//建立命名管道
	HANDLE my_pipe=CreateNamedPipe(
		           "\\\\.\\Pipe\\Test",
				   PIPE_ACCESS_DUPLEX,
				   PIPE_TYPE_BYTE|PIPE_READMODE_BYTE,
				   1,
				   0,
				   0,
				   1000,
				   NULL);
	printf("Pipe server running...\n");

	//等待連線
	if(ConnectNamedPipe(my_pipe,NULL)==FALSE)
	{
		CloseHandle(my_pipe);   
		printf("建立連線失敗!");   
		return 0;
	}
	else
	{
	    while(1)
		{
			//接收資料
			ReadFile(my_pipe,Buffer,sizeof(Buffer),&ReadNum,NULL);
			Buffer[ReadNum]='\0';
			printf("來自客戶端的資料:  %s \n",Buffer);
            
			//傳送資料
			char *Data="I am a pipe server !";
			WriteFile(my_pipe,Data,strlen(Data),&ReadNum,NULL);

		}
        //關閉管道
		DisconnectNamedPipe(my_pipe);
	}
}
客戶端程式:
#include
#include

int main()
{
	char Data[256]="I am client !";
	char Buffer[256];
	DWORD WriteNum;
	printf("pipe client is running!\n");

    //檢查管道是否存在
	WaitNamedPipe("\\\\.\\Pipe\\Test",NMPWAIT_WAIT_FOREVER);

    //開啟管道
	HANDLE hPipe=CreateFile("\\\\.\\Pipe\\Test",
		                     GENERIC_READ|GENERIC_WRITE,
							 0,
							 NULL,
							 OPEN_EXISTING,
							 FILE_ATTRIBUTE_NORMAL,
							 NULL);

	while(1)
	{
		//寫入管道
		WriteFile(hPipe,Data,strlen(Data),&WriteNum,NULL);
        getchar();

		//讀取管道
		ReadFile(hPipe,Buffer,sizeof(Buffer),&WriteNum,NULL);
		Buffer[WriteNum]='\0';
		printf("來自伺服器的資料: %s",Buffer);
	}

	CloseHandle(hPipe); 
	return 0;
}




相關文章