The Windows Pipes Programming - windows“管道”编程 之 "匿名管道"

何为“管道”?

“管道”是进程间通讯的一段共享内存区域。创建管道的进程成为管道服务器,连接到管道上的进程成为管道客户端。一个进程向管道写数据,其他进程可以从管道中读取数据。

“管道的分类”

管道分为两种,匿名管道和命名管道。匿名管道比命名管道需要的开销要小,但是提供的功能要少。管道在这里的含义暗示着它是一种连接信息的管子。管子有两端,单工通讯的管道允许在写端的进程把信息写入管子,在读端的进程读取管道中的信息。全双工通讯的管道允许在两端进行读写。

匿名管道提供单工通讯,没有名称。并且只能用于本地,不能通过网络通讯。

命名管道是一个有名称,能提供单工或全双工通讯的管子。它允许一个管道服务器,多个管道客户端。所有命名管道的实例共享一个管道名称,但是每个实例有它自己的缓冲区和句柄,并且为每个服务器/客户端通讯提供单独的信息传输渠道.这种方式允许多个管道客户端同时使用命名管道.任何命名管道都可以被任何进程访问,但是受制与安全检测策略.因此命名管道可以方便的区分相关与不相关的进程.

任何进程都可以作为服务器或者客户端,这使得p2p通信成为可能.这里管道服务器是指创建管道的进程,管道客户端是指连接到一个命名管道实例上的进程.管道服务器端使用CreateNamedPipe创建命名管道,使用ConnectNamedPipe接收连接请求.管道客户端使用CreateFile 和CallNamedPipe连接命名管道.

命名管道可以为本地或者通过网络与远程电脑中的进程提供通讯.如果你仅仅想让命名管道运行在本地,可以用本地RPC策略或者禁止访问NT AUTHORITY\NETWORK.

匿名管道”使用示例

代码要实现的功能就是创建两个控制台程序,一个控制台写消息,另一个控制台收消息。这是子父进程通信中匿名管道的典型用法,我们先直观看看这个示例是怎么工作的:

 

左边是父控制台,右边是子控制台。左边输入字符,右边就会显示出来:

下面是代码:

父控制台
 1 #include "UnNamedPipe.h"
 2 #include <iostream>
 3 
 4 using namespace std;
 5 
 6 HANDLE g_hReadPipe;
 7 HANDLE g_hWritePipe;
 8 
 9 int main()
10 {
11     LPTSTR errbuff;
12     char strBuff[256] = {0};
13     char* QUITCHAR = "q";
14     CUnNamedPipe myPipe;
15     SECURITY_ATTRIBUTES saAttr;
16     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
17     saAttr.bInheritHandle = TRUE; 
18     saAttr.lpSecurityDescriptor = NULL; 
19     STARTUPINFO siStartInfo;
20     PROCESS_INFORMATION piProcInfo;
21     DWORD nWriteTo;
22     TCHAR szAppName[] = TEXT("C:\\Users\\user\\Documents\\Visual Studio 2010\\Projects\\PipeWorkShop\\Debug\\AnonymousPipeClientTest.exe"); 
23     if(!myPipe.CreatePipe(g_hReadPipe, g_hWritePipe, saAttr, 0))
24     {
25         DWORD d = GetLastError();
26         FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER  | 
27             FORMAT_MESSAGE_IGNORE_INSERTS  | 
28             FORMAT_MESSAGE_FROM_SYSTEM,
29             NULL,
30             d, 
31             LANG_NEUTRAL,
32             (LPTSTR) & errbuff,
33             0 ,
34             NULL );
35         cout<<"can not create pipe!"<<endl;
36         return 1;
37     }
38 
39     if(!SetHandleInformation(g_hReadPipe, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
40     {
41         cout<<"set handle property error!"<<endl;
42     }
43     /*if(!SetHandleInformation(g_hWritePipe, HANDLE_FLAG_INHERIT, 0))
44     {
45         cout<<"set handle property error!"<<endl;
46     }*/
47     ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
48     siStartInfo.cb = sizeof(STARTUPINFO); 
49     siStartInfo.hStdInput = g_hReadPipe;
50     siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
51     siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
52     
53     if(!CreateProcess(szAppName, NULL, NULL, NULL, TRUE,CREATE_NEW_CONSOLE, NULL,NULL, &siStartInfo, &piProcInfo))
54     {
55         DWORD d = GetLastError();
56         FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER  | 
57                      FORMAT_MESSAGE_IGNORE_INSERTS  | 
58                      FORMAT_MESSAGE_FROM_SYSTEM,
59                      NULL,
60                      d, 
61                      LANG_NEUTRAL,
62                      (LPTSTR) & errbuff,
63                       0 ,
64                      NULL );
65 
66         cout<<"can't create process:"<<szAppName<<endl;
67         cout<<errbuff;
68         return 0;
69     }
70     cout<<"press q to quit, others to show!"<<endl;
71     while (cin>>strBuff )
72     {
73         while(strBuff[0]!=0)
74         {
75             if(!WriteFile(g_hWritePipe, strBuff, sizeof strBuff, &nWriteTo, NULL))
76             {
77                 cout<<"write file error!"<<endl;
78                 break;
79             }
80             if(strcmp(strBuff, QUITCHAR) == 0)
81             {
82                 return 0;;
83             }
84             ZeroMemory(strBuff, sizeof(strBuff));
85         }
86         
87     }
88     CloseHandle(piProcInfo.hProcess);
89     CloseHandle(piProcInfo.hThread);
90 
91     myPipe.ClosePipe(g_hReadPipe);
92     myPipe.ClosePipe(g_hWritePipe);
93 
94     return 0;
95 }
子控制台
 1 #include <Windows.h>
 2 #include <iostream>
 3 
 4 using namespace std;
 5 int main()
 6 {
 7     HANDLE hStdin, hStdout;
 8     char buff[256] = {0};
 9     char* QUIT = "q";
10     DWORD dwRead;
11     DWORD dwWrite;
12     hStdin = GetStdHandle(STD_INPUT_HANDLE);
13     hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
14     if (hStdin == INVALID_HANDLE_VALUE || hStdout == INVALID_HANDLE_VALUE)
15     {
16         return 1;
17     }
18     cout<<"client is working!"<<endl;
19     while(1)
20     {
21         if(ReadFile(hStdin, buff, 256, &dwRead, NULL) && buff[0] != 0)
22         {
23             if(strcmp(buff,QUIT) == 0)
24                 return 0;
25             else
26             {
27                 cout<<buff<<endl;
28                 //WriteFile(hStdout, buff, 256, &dwWrite, NULL); there is someting interesting if you use this instead of before one.
29                 ZeroMemory(buff, sizeof buff);
30             }
31             
32         }
33         
34         Sleep(500);
35     }
36     cout<<"client will shutdown in 3 sec!"<<endl;
37     Sleep(3000);
38     return 0;
39 }

接口代码:

 1 /********************************************************************
 2     created:    2012/08/11
 3     file name:    IPipe.h
 4     author:        baesky
 5     http://www.cnblogs.com/Baesky/
 6     purpose:    Give a public interface.
 7 *********************************************************************/
 8 
 9 #pragma once
10 #include <Windows.h>
11 class IPipe
12 {
13 public:
14     virtual bool CreatePipe(HANDLE& hReadPipe, HANDLE& hWritePipe, SECURITY_ATTRIBUTES& lpPipeAttributes, DWORD nBuffSize) = 0;
15     virtual bool ClosePipe(HANDLE hPipe) = 0;
16 };
UnNamedPipe.h
 1 #pragma once
 2 #include "IPipe.h"
 3 
 4 
 5 class CUnNamedPipe:public IPipe
 6 {
 7 public:
 8     CUnNamedPipe(void);
 9     ~CUnNamedPipe(void);
10 
11     bool CreatePipe(HANDLE& hReadPipe, HANDLE& hWritePipe, SECURITY_ATTRIBUTES& lpPipeAttributes, DWORD nBuffSize);
12     bool ClosePipe(HANDLE hPipe);
13 };
UnNamedPipe.cpp
 1 #include "UnNamedPipe.h"
 2 
 3 
 4 CUnNamedPipe::CUnNamedPipe(void)
 5 {
 6 }
 7 
 8 
 9 CUnNamedPipe::~CUnNamedPipe(void)
10 {
11 }
12 
13 bool CUnNamedPipe::CreatePipe(HANDLE& hReadPipe, HANDLE& hWritePipe, SECURITY_ATTRIBUTES& lpPipeAttributes, DWORD nBuffSize)
14 {
15     return ::CreatePipe(&hReadPipe, &hWritePipe, &lpPipeAttributes, nBuffSize);
16 }
17 
18 bool CUnNamedPipe::ClosePipe(HANDLE hPipe)
19 {
20     return CloseHandle(hPipe);
21 }

 

 

posted on 2012-08-12 11:39  Meta.Grfx  阅读(2346)  评论(3编辑  收藏  举报

导航