c++下使用命名管道实现进程间通信

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++下使用命名管道实现进程间通信相关的知识,希望对你有一定的参考价值。

  前面已经使用邮槽实现过进程间通信:http://www.cnblogs.com/jzincnblogs/p/5192654.html ,这里使用命名管道实现进程间通信。

  与邮槽不同的是,命名管道在进程间传输数据是基于连接且可靠的传输方式,所以命名管道传输数据只能一对一。使用命名管道的步骤如下:

  ①创建命名管道,命名管道通过调用函数CreateNamedPipe()创建,函数原型如下:

 1 HANDLE WINAPI CreateNamedPipe(
 2   _In_     LPCTSTR               lpName,
 3   _In_     DWORD                 dwOpenMode,
 4   _In_     DWORD                 dwPipeMode,
 5   _In_     DWORD                 nMaxInstances,
 6   _In_     DWORD                 nOutBufferSize,
 7   _In_     DWORD                 nInBufferSize,
 8   _In_     DWORD                 nDefaultTimeOut,
 9   _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes
10 );

  各参数的设置方法可参考MSDN:https://msdn.microsoft.com/zh-cn/biztalk/aa365150(v=vs.80)

  ②连接命名管道。当用户成功创建命名管道后便可调用相关函数连接命名管道,对于服务器而言,可以调用函数ConnectNamedPipe()等待客户端的连接请求,函数原型如下:

1 BOOL WINAPI ConnectNamedPipe(
2   _In_        HANDLE       hNamedPipe,
3   _Inout_opt_ LPOVERLAPPED lpOverlapped
4 );

  参数的设置方法:https://msdn.microsoft.com/zh-cn/biztalk/aa365150(v=vs.80)

  对于客户端而言,在连接服务器创建的命名管道前需要判断该命名管道是否可用,可调用函数WaitNamedPipe()实现,函数使用方法可参考MSDN:https://msdn.microsoft.com/zh-cn/subscriptions/aa365800

  当WaitNamedPipe()调用成功后,便可使用CreateFile()将命名管道打开已获得管道的句柄。

  ③读写命名管道,对命名管道的读写操作利用函数ReadFile()和WriteFile()完成,与上一篇的邮槽类似。

  服务器和客户端的实现代码如下:

  服务器端:

 1 //server
 2 //命名管道采用基于连接的可靠传输方式,只能一对一传输
 3 #include <windows.h>
 4 #include <iostream>
 5 
 6 #define BUF_SIZE 1024
 7 
 8 using std::cerr;
 9 using std::cout;
10 using std::endl;
11 
12 int main()
13 {
14     HANDLE h_pipe;
15     char buf_msg[BUF_SIZE];
16     DWORD num_rcv; //实际接收到的字节数
17     //创建命名管道,命名为MyPipe,消息只能从客户端流向服务器,读写数据采用阻塞模式,字节流形式,超时值置为0表示采用默认的50毫秒
18     h_pipe = ::CreateNamedPipe("\\\\\\\\.\\\\pipe\\\\MyPipe", PIPE_ACCESS_INBOUND, PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUF_SIZE, BUF_SIZE, 0, nullptr);
19     if (h_pipe == INVALID_HANDLE_VALUE)
20     {
21         cerr << "Failed to create named pipe!Error code: " << ::GetLastError() << "\\n";
22         system("pause");
23         return 1;
24     }
25     else
26     {
27         cout << "Named pipe created successfully...\\n";
28     }
29     //等待命名管道客户端连接
30     if (::ConnectNamedPipe(h_pipe, nullptr))
31     {
32         cout << "A client connected...\\n";
33         memset(buf_msg, 0, BUF_SIZE);
34         //读取数据
35         if (::ReadFile(h_pipe, buf_msg, BUF_SIZE, &num_rcv, nullptr))
36         {
37             cout << "Message received: " << buf_msg << "\\n";
38         }
39         else
40         {
41             cerr << "Failed to receive message!Error code: " << ::GetLastError() << "\\n";
42             ::CloseHandle(h_pipe);
43             ::system("pause");
44             return 1;
45         }
46     }
47     ::CloseHandle(h_pipe);
48     ::system("pause");
49     return 0;
50 }

  客户端:

 1 //client
 2 #include <windows.h>
 3 #include <iostream>
 4 
 5 #define BUF_SIZE 1024
 6 
 7 using std::cerr;
 8 using std::cout;
 9 using std::endl;
10 
11 int main()
12 {
13     HANDLE h_pipe;
14     char buf_msg[] = "Test for named pipe...";
15     DWORD num_rcv; //实际接收到的字节数
16     cout << "Try to connect named pipe...\\n";
17     //连接命名管道
18     if (::WaitNamedPipe("\\\\\\\\.\\\\pipe\\\\MyPipe", NMPWAIT_WAIT_FOREVER))
19     {
20         //打开指定命名管道
21         h_pipe = ::CreateFile("\\\\\\\\.\\\\pipe\\\\MyPipe", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
22         if (h_pipe == INVALID_HANDLE_VALUE)
23         {
24             cerr << "Failed to open the appointed named pipe!Error code: " << ::GetLastError() << "\\n";
25             ::system("pause");
26             return 1;
27         }
28         else
29         {
30             if (::WriteFile(h_pipe, buf_msg, BUF_SIZE, &num_rcv, nullptr))
31             {
32                 cout << "Message sent successfully...\\n";
33             }
34             else
35             {
36                 cerr << "Failed to send message!Error code: " << ::GetLastError() << "\\n";
37                 ::CloseHandle(h_pipe);
38                 ::system("pause");
39                 return 1;
40             }
41         }
42         ::CloseHandle(h_pipe);
43     }
44     ::system("pause");
45     return 0;
46 }

 

以上是关于c++下使用命名管道实现进程间通信的主要内容,如果未能解决你的问题,请参考以下文章

Windows进程间通信—命名管道

Linux进程间通信

进程间通信——管道

Linux进程间通信

命名管道

Linux入门进程间的通信