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 }
时间: 2024-10-06 23:14:05

c++下使用命名管道实现进程间通信的相关文章

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

创建命名管道 命名管道常常用于应用程序之间的通迅,由于不需要进行序列化和反序列化操作,效率是非常高的.相比TCP通信方式,效率更高,但比共享内存要低点.命名管道可以在本地机器或者局域网内机器实现进程间通信,所以是最佳的通信方式. 创建一个NamedPipeServerStream: NamedPipeServerStream pipeServer = new NamedPipeServerStream(_pipName, PipeDirection.InOut, 10); 这里表示命名管道服务器

Linux下进程间通信之命名管道(FIFO)

匿名管道的一个不足之处是没有名字,因此,只能用于具有亲缘关系的进程间通信.在命名管道(FIFO)提出后,该限制得到了克服.FIFO不同于pipe在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中.命名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够相互通信. FIFO总是按照先进先出的原则工作,第一个被写入的数据将首先从管道中读出. Linux下有两种方式创建FIFO,一是在shell下交互的建立一个命名管道,二是在程序中使用系统函

Linux进程间通信 -- 使用命名管道

在前一篇文章—— Linux进程间通信 -- 使用匿名管道 中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关的的进程之间交换数据带来了不方便.这里将会介绍进程的另一种通信方式——命名管道,来解决不相关进程间的通信问题. 一.什么是命名管道 命名管道也被称为FIFO文件,它是一种特殊类型的文件,它在文件系统中以文件名的形式存在,但是它的行为却和之前所讲的没有名字的管道(匿名管道)类似. 由于Linux中所有

进程间通信——命名管道

概念 管道一个不足之处是没有名字,因此只能用于具有亲缘关系的进程间通信,命名管道(named pipe或FIFO)解决了这一问题. FIFO提供一个路径名与之关联,以FIFO文件的形式存储于文件系统中.文件系统中路径名是全局的,各进程都可以访问,因此可以用文件系统中的路径名来标识一个IPC通道. 对文件系统来说,匿名管道(管道)是不可见的,它的作用仅限于在父进程和子进程两个进程间进行通信.而命名管道是一个可见的文件,因此,他可以用于任意两个进程间进行通信,不管这两个进程是不是父子进程,也不管这两

进程间通信(5) - 命名管道(FIFO)

1. 前言 本篇文章的所有例子,基于RHEL6.5平台.前一篇文章介绍了匿名管道.点此链接. 2.介绍 管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(named pipe或FIFO)提出后,该限制得到了克服.FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中.这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间),因此,

进程间通信之命名管道

命名管道(FIFO)是进程间通信的一种方式,DEMO如下: // 写进程 int main(int argc, char **argv) { char filename[] = "/tmp/my_fifo"; if (mkfifo(filename, 0777) < 0) { perror("mkfifo error"); exit(1); } int fd = open(filename, O_WRONLY); char buffer[128] = &quo

进程间通信(1)---匿名管道与命名管道

管道是进程间通信一种基本的的一种方式,管道又分为两种,匿名管道和命名管道,先说匿名管道 匿名管道(pipe) #include <unistd.h> int pipe(int filedes[2]); 调用pipe时会在内核中开辟一个缓冲区,使用时fileds[0]为输出端,fileds[1]为写入端口,调用成功时返回0,失败时返回-1: pipe的特点: 1:它只能在有血缘关系的进程间进行通信. 2:它只能进行单项通信,一个进程读,另一个只能写. 3:它是一种流式服务. 4:它的生命周期跟随

Linux进程间通信-命名管道

前面我们讲了进程间通信的一种方式,匿名管道.我们知道,匿名管道只能用于父子关系的进程之间.那么没有这种关系的进程之间该如何进行数据传递呢? 1.什么是命名管道 匿名管道是在缓存中开辟的输出和输入文件流的空间,只能用于父子关系的进程之间.因为父子进程的输入和输出文件描述符是一致的.命名管道是一种实际存在的FIFO文件,称作“管道文件”,用于不同进程之间,命名管道进程间打开同一个FIFO文件,进行数据传递.我们可以像普通文件一样操作FIFO文件.不同进程,引用同一个FIFO文件,进行数据传递. 2.

Linux系统编程——进程间通信:命名管道(FIFO)

命名管道的概述 无名管道,由于没有名字,只能用于亲缘关系的进程间通信(更多详情,请看<无名管道>).为了克服这个缺点,提出了命名管道(FIFO),也叫有名管道.FIFO 文件. 命名管道(FIFO)不同于无名管道之处在于它提供了一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中,这样,即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过 FIFO 相互通信,因此,通过 FIFO 不相关的进程也能交换数据. 命名管道(FIFO)和无名管道(pipe)有一