💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力! 👍点赞、收藏与分享:觉得这篇文章对你有帮助吗?别忘了点赞、收藏并分享给更多的小伙伴哦!你们的支持是我不断进步的动力! 🚀分享给更多人:如果你觉得这篇文章对你有帮助,欢迎分享给更多对Linux OS感兴趣的朋友,让我们一起进步!
命名管道(Named Pipe)是一种用于进程间通信(IPC)的机制,它允许不同进程之间通过一个命名的通道交换数据。与匿名管道不同,命名管道是通过一个系统级的文件路径来标识和访问,允许不同的进程在不同的时间、甚至不同的机器上进行通信。
允许不具有血缘关系的进程之间进行通信,数据使用FIFO原则进行数据传输。
mkfifo filename
该指令将会创建命名管道filename(管道名称)。
int mkfifo(const char *pathname, mode_t mode);
参数说明:
返回值:
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
int main() {
const char *fifo_path = "/tmp/my_fifo";//命名管道路径
// 创建命名管道
if (mkfifo(fifo_path, 0666) == -1) {
perror("mkfifo failed");
return 1;
}
printf("FIFO created successfully\n");//成功是打印该内容
return 0;
}
在这个示例中,mkfifo 创建了一个名为 /tmp/my_fifo 的命名管道,权限设置为 0666,即文件的所有者、用户组和其他用户均可读写。
特性 | 命名管道(Named Pipe) | 匿名管道(Anonymous Pipe) |
---|---|---|
标识方式 | 有文件路径,可以通过路径访问 | 没有文件路径,仅通过管道描述符访问 |
作用范围 | 支持不同进程间通信,甚至跨系统通信 | |
创建方式 | 使用mkfifo()创建 | 使用pipe()创建 |
生命周期 | 用户控制,管道文件存在于文件系统中 | 进程结束后自动销毁 |
阻塞行为 | 支持阻塞,写操作阻塞直到有读进程 | 支持阻塞,写操作阻塞直到有读进程 |
使用场景 | 不同进程间通信 | 父子进程之间通信 |
命名管道具有更强的灵活性,适用于跨进程、跨系统的复杂场景;而匿名管道则更简单,适用于父子进程间的简单数据传输。
"用户控制”则表示,管道的生命周期由用户管理,用户可以决定管道的创建、删除时机,并且管道不会自动销毁,直到用户删除它。
特点与匿名管道相似,唯一不同的是它可以让毫不相干的进程之间进行通信。
用命名管道(Named Pipe)实现客户端与服务端通信是一种常见的进程间通信(IPC)方式。在这种模式下,服务端和客户端通过一个共享的命名管道进行数据交换。命名管道提供了一个通信通道,使得它们可以在不同的进程间进行双向数据传输。由于命名管道是一种通过文件系统实现的通信机制,因此客户端和服务端可以通过文件路径访问该管道。
命名管道的工作原理基于先进先出规则,即数据写入管道的顺序会按照写入的顺序被读取。它在进程间提供一个缓冲区,允许数据从一个进程流向另一个进程。
在客户端和服务端通信中,服务端通常是管道的创建者,而客户端则是通过管道进行读取和写入操作。
为什么要使用命名管道(FIFO)?
创建命名管道:
int n = mkfifo(FIFO_FILE, 0666); // 创建管道,文件名为 FIFO_FILE
if (n != 0) {
std::cerr << "mkdir fifo error" << std::endl;
return 1;
}
服务端的工作是打开命名管道文件,读取客户端发送过来的消息并显示。
int fd = open(FIFO_FILE, O_RDONLY); // 以只读方式打开命名管道
if (fd < 0) {
std::cerr << "open fifo error" << std::endl;
return 2;
}
open() 用于打开已经创建的命名管道文件。这里我们以 O_RDONLY(只读)方式打开它,意味着服务端只是从管道中读取数据。
如果管道无法打开,输出错误信息并返回 2。
char buffer[1024];
while (true) {
int n = read(fd, buffer, sizeof(buffer) - 1); // 从管道读取数据
if (n > 0) {
buffer[n] = 0; // 确保字符串结束
std::cout << "client say# " << buffer << std::endl; // 打印客户端消息
}
}
read() 函数从命名管道中读取数据,直到管道中没有数据可读。buffer 存储读取到的数据。
如果读取成功,将数据输出到控制台。
通过 n 判断读取的字节数,如果大于 0,说明读取成功。
close(fd); // 关闭管道
完成数据读取后,关闭管道文件描述符。
客户端需要向命名管道写入消息。在每次输入后,客户端会将用户输入的消息写入管道,供服务端读取。
int fd = open(FIFO_FILE, O_WRONLY); // 以只写方式打开命名管道
if (fd < 0) {
std::cerr << "open fifo error" << std::endl;
return 2;
}
open() 用于打开管道文件,O_WRONLY 表示只写打开管道。客户端仅通过该管道写入数据。
如果打开失败,输出错误并返回 2。
发送信息:
while (true) {
std::cout << "Please Enter# ";
std::string message;
std::cin >> message; // 从用户输入读取消息
int n = write(fd, message.c_str(), message.size()); // 将消息写入管道
if (n > 0) {
// 写入成功
}
}
std::cin >> message 用于从用户输入获取消息。
write() 用于将消息写入管道。如果消息成功写入,n 返回写入的字节数。
关闭管道:
close(fd); // 关闭管道
客户端发送完消息后,关闭管道。
#pragma once
#define FIFO_FILE "fifo" // 定义命名管道的文件路径
在 common.hpp 文件中定义一个宏 FIFO_FILE,用于存储命名管道的路径。在客户端和服务端中都使用这个路径,确保一致性。
本文介绍了基于命名管道(FIFO)实现客户端与服务器实时通信的过程。命名管道是一种通过文件路径进行进程间通信的机制,支持不同进程之间的数据传输,基于FIFO(先进先出)原则。通过 mkfifo() 函数可以创建命名管道,客户端和服务端通过管道文件进行数据交换。服务端创建并打开管道以读取数据,客户端通过管道向服务端写入消息。命名管道的优势在于不需要网络连接,适用于同一台机器上的进程通信。通过合适的同步与阻塞机制,客户端与服务端能够顺利实现数据传输。
完整代码(如下):
server.cc
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstring>
#include <unistd.h>
#include "common.hpp"
int main()
{
umask(0);
int n = mkfifo(FIFO_FILE, 0666);
if(n != 0)
{
std::cerr << "mkdir fifo error" << std::endl;
return 1;
}
int fd = open(FIFO_FILE,O_RDONLY);
if(fd < 0)
{
std::cerr << "open fifo error" << std::endl;
return 2;
}
char buffer[1024];
while(true)
{
int n = read(fd,buffer,sizeof(buffer) -1);
if(n > 0)
{
buffer[n] = 0;
std::cout << "client say# " << buffer << std::endl;
}
}
close(fd);
return 0;
}
client.cc
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstring>
#include <unistd.h>
#include "common.hpp"
int main()
{
int fd = open(FIFO_FILE,O_WRONLY);
if(fd < 0)
{
std::cerr << "open fifo error" << std::endl;
return 2;
}
while(true)
{
std::cout << "Please Enter# ";
std::string message;
std::cin >> message;
int n = write(fd, message.c_str(),message.size());
if(n > 0)
{
}
}
close(fd);
return 0;
}
comm.hpp
#pragma once
#define FIFO_FILE "fifo"
makefile
.PHONY:all
all:client server
client:client.cc
g++ -o $@ $^ -std=c++11
server:server.cc
g++ -o $@ $^ -std=c++11
.PHONY:clean
clean:
rm -f client server
上述代码可以实现两者进行通信。
演示图片(如下图):
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有