当前位置: 首页 > news >正文

Linux系统之----命名管道模拟实现客户端、服务器

一、Makefile的编写

这里的Makefile文件的编写与前面不太一样,我们先看正确的代码:

.PHONY:all
all:server clientserver:server.cppg++ -o $@ $^ -std=c++11client:client.cpp	g++ -o $@ $^ -std=c++11.PHONY:clean
clean:rm -f clientrm -f server

此处的all不可以省略,如果省略了你之后在make时只会编译server.cpp文件,client.cpp不会编译,不信可以试一下~

讲的专业一点就是,在这个 Makefile 中,all 是一个 PHONY 目标,它依赖于 serverclient 两个目标。这意味着当你运行 make 命令时,如果没有指定其他目标,make 将默认执行 all 目标,从而编译 server.cppclient.cpp 文件。

二、项目本体的编写

由于客户端和服务端都是通过命名管道来写的,所以二者基本逻辑相同,故项目组成由三部分:

client.cpp       server.cpp      NamePipe.hpp,但是为了简化NamePipe.hpp中的代码,我们在额外设计一个common.hpp来辅助减轻一下其代码量,主要用于存放头文件以及一些全局变量啥的~

三、NamedPipe.hpp的编写

在此文件中,我们要构造出命名管道的模样,即命名管道的模拟实现,包括类的初始化,析构以及各种库函数的实现。我们主要分享一下方法函数实现部分内容~

方法函数主要包括管道的创建,读,写,移除,关闭,以及只读打开还有只写打开

#pragma once
#include "common.hpp"
const int defaultfd = -1; // 检查错误用的
class NamedPipe
{
public:NamedPipe(const string &name): _name(name), _fd(defaultfd){}~NamedPipe(){}bool Create(){// 1.创建管道文件int n = mkfifo(fifoname.c_str(), mode);if (n == 0){cout << "mkfifo success" << endl;}else{perror("mkfifo");return false;}return true;}void Close(){if (_fd == defaultfd) // 这里如果open那里没打开文件,_fd就为-1,这里直接返回{return;}elseclose(_fd);}bool OpenForRead(){_fd = open(fifoname.c_str(), O_RDONLY);if (_fd < 0){// 打开失败perror("open");return false;}cout << "open file success" << endl;return true;}bool OpenForWrite(){_fd = open(fifoname.c_str(), O_WRONLY);if (_fd < 0){perror("open");return false;}return true;}// 输入参数:const &// 输出参数:*// 输入输出参数:&bool Read(string *out){char buffer[SIZE]={0};ssize_t num = read(_fd,buffer,sizeof(buffer)-1);if(num>0){//读取成功buffer[num]=0;*out =buffer;}else{return false;}return true;}void Write(const string &in){write(_fd,in.c_str(),in.size());}void Remove(){int m=unlink(fifoname.c_str());(void)m;}
private:string _name; // path+nameint _fd;      // who
};

我们还要定义一些变量,不如再创一个文件,就叫commom.hpp吧

#ifndef __COMMON_HPP__
#define __COMMON_HPP__#include <iostream>
#include <cstdio>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>using namespace std;
const string fifoname="fifo";
mode_t mode=0666;
#define SIZE 128#endif

四、client.cc和server.cc的编写

这是client.cc

#include"NamedPipe.hpp"int main()
{NamedPipe namedpipe(fifoname);namedpipe.OpenForWrite();while(true){cout<<"Please Enter# ";string line;getline(cin,line);namedpipe.Write(line);}namedpipe.Close();return 0;
}

这是server.cc

#include "NamedPipe.hpp"int main()
{NamedPipe namedpipe(fifoname);namedpipe.Create();namedpipe.OpenForRead();// 2. 打开文件,就和普通文件没有区别// 命名管道操作特点: 打开一端,在另一端没打开的时候,open会阻塞// 3. 通信string message;while(true){bool res=namedpipe.Read(&message);if(!res)break;      cout<<"client say@"<<message<<endl;}// 4. 归还资源cout<<"对方已将你删除!!!"<<endl;namedpipe.Close();namedpipe.Remove();return 0;
}

五、运行结果

结果解释:client端发送的消息可以在server端接收到,在使用时,先连接./server,再连接./client

(ps:作者小趴菜不是舔gou哈~)

好了,这个小项目基本到这了,感兴趣的可以给尝试改造为双端的,本文实现的仅仅是单端通信~

http://www.dtcms.com/a/354943.html

相关文章:

  • ImageToPromptAI-AI图像转提示词生成器
  • ftp命令批量删除服务器上的文件
  • 关于我在一个优惠券系统中rocketMQ消息幂等性自定义注解的处理
  • 使用reCAPTCHA提升WordPress网站安全性
  • 驱动开发系列67 - NVIDIA 开源GPU驱动open-gpu-kernel-modules分析-驱动初始化
  • Java自定义程序使用Ollama实现本地ai调用
  • Java-反射机制
  • Java 多线程环境下的全局变量缓存实践指南
  • PyTorch 张量核心知识点
  • 【物联网】什么是 Arduino Nano 33 IoT?
  • 基于springboot的二手车交易系统
  • WEEX唯客上线C2C交易平台:打造安全便捷的用户交易体验
  • FISCO-BCOS-Python 模板
  • 上海控安:GB 44495-2024《汽车整车信息安全技术要求》标准解读和测试方案
  • 动手学深度学习(pytorch版):第七章节—现代卷积神经网络(6)残差网络(ResNet)
  • Ubuntu 使用百度云的bypy上传和下载数据
  • ArcGIS+Fragstats:土地利用统计分析、景观格局指数计算与地图制图
  • 终极实战 - 全链路排查一次“502 Bad Gateway”
  • Linux并发与竞争
  • 达梦数据库-重做日志文件(三)-自动化迁移脚本和检查 磁盘 I/O 性能建议
  • 详细介绍Linux 内存管理 匿名页面和page cache页面有什么区别?
  • Mybatis 与 Springboot 集成过程详解
  • vue有哪些优缺点
  • 前端实现Linux查询平台:打造高效运维工作流
  • 从图卷积网络(GCN)到简化图卷积网络(SGC)的对话
  • RAG系统深度优化全攻略:从理论到实践的高性能实现
  • 【C语言16天强化训练】从基础入门到进阶:Day 14
  • NVFP4量化技术深度解析:4位精度下实现2.3倍推理加速
  • 内网对抗-红日靶场4通关详解
  • 财务数据报销画像技术实现:从数据采集到智能决策的全流程解析