【0805作业】Linux中 AB终端通过两根有名管道进行通信聊天(半双工)(全双工)

作业一:打开两个终端,要求实现AB进程对话【两根管道】

打开两个终端,要求实现AB进程对话

  1. A进程先发送一句话给B进程,B进程接收后打印
  2. B进程再回复一句话给A进程,A进程接收后打印
  3. 重复1.2步骤,当收到quit后,要结束AB进程
  • 提示:两根管道

A终端代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>/***************************A终端***************************/int main(int argc, const char *argv[])
{//创建管道1    A终端写入--->管道1--->B终端读取if(mkfifo("./fifo",0664) < 0){if(errno != 17)//如果错误是已有管道,则跳过,可正常运行{perror("mkfifo");return -1;}}printf("mkfifo pipe1 success __%d__\n",__LINE__);//创建管道2    B终端写入--->管道2--->A终端读取if(mkfifo("./myfifo",0664) < 0){if(errno != 17){perror("mkfifo");return -1;}}printf("mkfifo pipe2 success __%d__\n",__LINE__);//以写的方式打开管道1int fd_w=open("./fifo",O_WRONLY);if(fd_w < 0){perror("open");return -1;}printf("open pipeA success __%d__\n",__LINE__);//以读的方式打开管道Bint fd_r=open("./myfifo",O_RDONLY);if(fd_r < 0){perror("open");return -1;}printf("open pipeB success __%d__\n",__LINE__);char buf[128]="";ssize_t res = 0;int c=-1;while(1){//管道1操作(写入数据)printf("请输入要对B说的话>>> ");fgets(buf,sizeof(buf),stdin);    //从终端获取数据buf[strlen(buf)-1] = '\0';   //将\n改成\0if((write(fd_w,buf,sizeof(buf))) < 0)  //将字符串写进管道A  {perror("write");return -1;}//当管道1的读段关闭,管道1的写段尝试写入数据,则管道破裂,退出进程//管道2操作(读取数据)bzero(buf,sizeof(buf));//清空字符串res=read(fd_r,buf,sizeof(buf));//读取B管道中的数据c=strcmp(buf,"quit");//将读到的数据与quit比较if(0 == c)//如果相同,c为0,达到退出条件,可以退出循环{break;}//printf("写入数据成功 res=%ld\n",res);if(res < 0)//read函数执行失败,返回负数{perror("read");return -1;}   if(0 == res)//read执行成功,但读到了0个数据`{printf("对方进程退出\n");break;}//打印从管道2中读取到的数据printf("B:%s\n",buf);}//关闭管道1、管道2close(fd_r);close(fd_w);return 0;
}

B终端代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>/***************************B终端***************************/  int main(int argc, const char *argv[])
{//创建管道1   A终端写入--->管道1--->B终端读取if(mkfifo("./fifo",0664) < 0){if(errno != 17){perror("mkfifo");return -1;}}printf("mkfifo pipe1 success __%d__\n",__LINE__);//创建管道2   B终端写入--->管道2--->A终端读取if(mkfifo("./myfifo",0664) < 0){if(errno != 17){perror("mkfifo");return -1;}}printf("mkfifo pipe2 success __%d__\n",__LINE__);//以读的方式打开管道1int fd_r=open("./fifo",O_RDONLY);if(fd_r < 0){perror("open");return -1;}printf("open pipe1 success __%d__\n",__LINE__);//以写的方式打开管道2int fd_w=open("./myfifo",O_WRONLY);if(fd_w < 0){perror("open");return -1;}printf("open pipe2 success __%d__\n",__LINE__);char buf[128]="";ssize_t res = 0;int c=-1;while(1){//管道1操作(读取数据)bzero(buf,sizeof(buf));res=read(fd_r,buf,sizeof(buf));c=strcmp(buf,"quit");//判断B终端输入的是否是quitif(0 == c){break;//是quit则退出进程}if(res < 0){perror("read");return -1;}if(0 == res ){printf("对方进程退出\n");break;}printf("A:%s\n",buf);//管道2操作(写入数据)printf("请输入>>> ");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = '\0';if((write(fd_w,buf,sizeof(buf))) < 0){perror("write");return -1;}//当管道2关闭,管道2的写段尝试写入数据,则管道破裂,退出进程}close(fd_r);close(fd_w);return 0;
}

A终端结果

ubuntu@ubuntu:02_fifo$ gcc 03_pipe_w.c -o w
ubuntu@ubuntu:02_fifo$ ./w
mkfifo pipe1 success __22__
mkfifo pipe2 success __33__
open pipeA success __42__
open pipeB success __50__
请输入要对B说的话>>> 你好,我是A
B:你好呀,我是B
请输入要对B说的话>>> 你吃饭了吗?
B:吃了,你呢
请输入要对B说的话>>> 不告诉你
ubuntu@ubuntu:02_fifo$ 

B终端结果

ubuntu@ubuntu:02_fifo$ gcc 02_pipe_r.c -o r
ubuntu@ubuntu:02_fifo$ ./r
mkfifo pipe1 success __22__
mkfifo pipe2 success __33__
open pipe1 success __42__
open pipe2 success __50__
A:你好,我是A
请输入>>> 你好呀,我是B
A:你吃饭了吗?
请输入>>> 吃了,你呢
A:不告诉你
请输入>>> quit
对方进程退出
ubuntu@ubuntu:02_fifo$ 

fd741777d8ed4957bfa812ba1a3af75e.png

作业二:在作业一的基础上,AB能随时发信息给对方(全双工)

此代码需要双方终端都输入quit才能结束对话

A终端代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>/***************************A终端***************************/int main(int argc, const char *argv[])
{umask(0);//创建管道1(发送)    A终端写入--->管道1--->B终端读取if(mkfifo("./fifo",0777) < 0){if(errno != 17)//如果错误是已有管道,则跳过,可正常运行{perror("mkfifo");return -1;}}printf("mkfifo pipe1 success __%d__\n",__LINE__);umask(0);//创建管道2(接收)    B终端写入--->管道2--->A终端读取if(mkfifo("./myfifo",0664) < 0){if(errno != 17){perror("mkfifo");return -1;}}printf("mkfifo pipe2 success __%d__\n",__LINE__);//创建子进程pid_t cpid=fork();//以写的方式打开管道1int fd_w=open("./fifo",O_WRONLY);if(fd_w < 0){perror("open");return -1;}printf("open pipeA success __%d__\n",__LINE__);//以读的方式打开管道Bint fd_r=open("./myfifo",O_RDONLY);if(fd_r < 0){perror("open");return -1;}printf("open pipeB success __%d__\n",__LINE__);char buf[128]="";ssize_t res = 0;int c=-1;if(0 == cpid)//子进程发送   fifo{while(1){//管道1操作(写入数据)fgets(buf,sizeof(buf),stdin);    //从终端获取数据buf[strlen(buf)-1] = '\0';   //将\n改成\0if((write(fd_w,buf,sizeof(buf))) < 0)  //将字符串写进管道A  {perror("write");                                                     return -1;}//当管道1的读段关闭,管道1的写段尝试写入数据,则管道破裂,退出进程if(strcmp(buf,"quit") == 0)//如果相同,c为0,达到退出条件,可以退出循环{break;}//printf("写入数据成功 res=%ld\n",res);}close(fd_w);_exit(0);}else if(cpid > 0)//父进程接收  myfifo{while(1){//管道2操作(读取数据)bzero(buf,sizeof(buf));//清空字符串res=read(fd_r,buf,sizeof(buf));//读取B管道中的数据if(res < 0)//read函数执行失败,返回负数{perror("read");return -1;}if(0 == res)//read执行成功,但读到了0个数据`{break;}if(strcmp(buf,"quit")==0)break;//打印从管道2中读取到的数据printf("B:%s\n",buf);}wait(NULL);close(fd_r);}//关闭管道1、管道2close(fd_r);close(fd_w);return 0;
}

B终端代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>/***************************B终端***************************/int main(int argc, const char *argv[])
{//创建管道1(接收)   A终端写入--->管道1--->B终端读取if(mkfifo("./fifo",0777) < 0){if(errno != 17){perror("mkfifo");return -1;}}printf("mkfifo pipe1 success __%d__\n",__LINE__);//创建管道2(发送)   B终端写入--->管道2--->A终端读取if(mkfifo("./myfifo",0777) < 0){if(errno != 17){perror("mkfifo");return -1;}}printf("mkfifo pipe2 success __%d__\n",__LINE__);//创建子进程pid_t cpid=fork();//以读的方式打开管道1int fd_r=open("./fifo",O_RDONLY);if(fd_r < 0){perror("open");return -1;}printf("open pipe1 success __%d__\n",__LINE__);//以写的方式打开管道2int fd_w=open("./myfifo",O_WRONLY);if(fd_w < 0){perror("open");return -1;}                                                                                      printf("open pipe2 success __%d__\n",__LINE__);char buf[128]="";ssize_t res = 0;//int c=-1;if(0 == cpid)//子进程接收  fifo{while(1){//管道1操作(读取数据)bzero(buf,sizeof(buf));res=read(fd_r,buf,sizeof(buf));if(res < 0){perror("read");return -1;}if(0 == res ){break;}if(strcmp(buf,"quit")==0)break;printf("A:%s\n",buf);}close(fd_r);_exit(0);}else if(cpid > 0)//父进程发送  myfifo{while(1){//管道2操作(写入数据)fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] = '\0';if((write(fd_w,buf,sizeof(buf))) < 0){perror("write");return -1;}//当管道2关闭,管道2的写段尝试写入数据,则管道破裂,退出进程if(strcmp(buf,"quit") == 0)//判断B终端输入的是否是quit{break;}}close(fd_w);wait(NULL);}else{perror("fork");return -1;}close(fd_r);close(fd_w);return 0;
}

结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/30486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

桥接模式-java实现

桥接模式 桥接模式的本质&#xff0c;是解决一个基类&#xff0c;存在多个扩展维度的的问题。 比如一个图形基类&#xff0c;从颜色方面扩展和从形状上扩展&#xff0c;我们都需要这两个维度进行扩展&#xff0c;这就意味着&#xff0c;我们需要创建一个图形子类的同时&#x…

API接口 |产品经理一定要懂的技术知识

什么是接口❓ 要理解接口是什么&#xff0c;首先理解一下为什么要用接口&#xff1f; 两个独立的系统&#xff0c;它们的数据或程序是独立的&#xff0c;这就使得它们无法直接访问对方的数据库或程序&#xff08;两个独立的数据相当于两个独立的家庭&#xff0c;每个家庭肯定是…

uniapp 运用Promise实现多图片上传

使用业务场景&#xff0c;循环多个图片上传控件&#xff0c;每一个上传到指定字段&#xff1b; dom结构如下&#xff1a; <u-form :model"userForm" :rules"rules" ref"uForm" labelWidth"160"> <u-form-item v-for"…

【MMU】认识 MMU 及内存映射的流程

MMU&#xff08;Memory Manager Unit&#xff09;&#xff0c;是内存管理单元&#xff0c;负责将虚拟地址转换成物理地址。除此之外&#xff0c;MMU 实现了内存保护&#xff0c;进程无法直接访问物理内存&#xff0c;防止内存数据被随意篡改。 目录 一、内存管理体系结构 1、…

内网穿透:实现公网访问内网群晖NAS的方法

公网远程访问内网群晖NAS 7.X版 【内网穿透】 文章目录 公网远程访问内网群晖NAS 7.X版 【内网穿透】前言1. 在群晖控制面板找到“终端机和SNMP”2. 建立一条连接公网数据隧道3. 获取公网访问内网群晖NAS的数据隧道入口 前言 群晖NAS作为应用较为广泛的小型数据存储中心&#…

SQL92 SQL99 语法 Oracle 、SQL Server 、MySQL 多表连接、Natural 、USING

SQL92 VS SQL 99 语法 92语法 内连接 from table1&#xff0c; table2 where table1.col table2.col 外连接 放在 从表 左连接&#xff1a; from table1&#xff0c; table2 where table1.col table2.col() 右连接&#xff1a; from table1&#xff0c; table2 where table…

自定义注解(Annontation)

目录 1.注解定义 2.元注解定义 3. 自定义注解&#xff08;自定义的注解名称相同的会覆盖原注解&#xff09; 4.Annotation架构&#xff08;元注解参数介绍&#xff09; 1.注解定义 注解是用来将任何的信息或元数据&#xff08;metadata&#xff09;与程序元素&#xff08;类…

苍穹外卖项目解读(四) 微信小程序支付、定时任务、WebSocket

前言 HM新出springboot入门项目《苍穹外卖》&#xff0c;笔者打算写一个系列学习笔记&#xff0c;“苍穹外卖项目解读”&#xff0c;内容主要从HM课程&#xff0c;自己实践&#xff0c;以及踩坑填坑出发&#xff0c;以技术&#xff0c;经验为主&#xff0c;记录学习&#xff0…

深度学习基础知识扫盲

深度学习 监督学习&#xff08;Supervised learning&#xff09;监督学习分类 无监督学习&#xff08;Non-supervised learning&#xff09;无监督学习的算法无监督学习使用场景 术语特征值特征向量特征工程&#xff08;Feature engineering&#xff09;特征缩放Sigmod functio…

大学生创业运营校园跑腿小程序怎么样?

校园跑腿小程序是一种基于移动互联网的服务平台&#xff0c;旨在为大学生提供便捷的跑腿服务。它可以连接大学生用户和需要代办事务的人群&#xff0c;实现多方共赢的局面。接下来&#xff0c;我将从需求背景、市场前景、功能特点等方面进行分析。 首先&#xff0c;校园跑腿小程…

使用mybatis-plus的updateById方法更新一个numeric(1)类型字段,sql成功执行,但是updates为0,更新失败的解决办法

使用mybatis-plus的updateById方法更新一个numeric(1)类型字段&#xff0c;sql成功执行&#xff0c;但是updates为0&#xff0c;更新失败的解决办法&#xff1a; 背景&#xff1a;我有一张表&#xff0c;有个启用禁用功能&#xff0c;没有放在编辑页面一起编辑保存&#xff0c;…

最强自动化测试框架Playwright-操作指南(3)-PO模式

playwright支持PO模式 创建页面对象 class SearchPage:def __init__(self, page):self.page pageself.search_term_input page.get_by_role("searchbox", name"输入搜索词")def navigate(self):self.page.goto("https://bing.com")def searc…

MySQL5.7数据库、Navicat Premium1.6可视化工具安装教程【详细教程】

文章目录 一、MySQL、Navicat、注册机地址二、安装&#xff08;一&#xff09;、MySQL安装&#xff08;二&#xff09;、Navicat Premium安装&#xff08;三&#xff09;、集活Navicat Premium 三、遇到的问题1、Are you sure your navicat has not beenpatched/modified befor…

TCP/UDP常见考点

1. TCP连接过程 1.1 三次握手 #mermaid-svg-MqcHXmAe6NVoJ6ZL {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-MqcHXmAe6NVoJ6ZL .error-icon{fill:#552222;}#mermaid-svg-MqcHXmAe6NVoJ6ZL .error-text{fill:#5522…

【高频面试题】微服务篇

文章目录 Spring Cloud1.Spring Cloud 5大组件有哪些&#xff1f;2.服务注册和发现是什么意思&#xff1f;Spring Cloud 如何实现服务注册发现&#xff1f;3.负载均衡如何实现的 ?4.什么是服务雪崩&#xff0c;怎么解决这个问题&#xff1f;5.微服务是怎么监控的 业务相关6.项…

python - 爬虫简介

什么是爬虫&#xff1f; 模拟浏览器对网站服务器发送请求解析服务器返回的响应数据&#xff0c;并保存数据 爬虫能获取哪些数据&#xff1f; 原则上所有可以通过浏览器获取的数据都可以爬取爬虫也只能获取爬取浏览器可以正常获取的数据 爬虫的应用场景&#xff1f; 数据分…

SQL - limit

介绍: limit 是限制的意思, 用于限制返回的查询结果的行数(可以通过limit指定查询多少行数据). MySQL支持limit语法, 用来完成分页. 用法: select 字段1, 字段2, ... from table_name limit offset, length;参数说明: offset: 起始行数, 从0开始计数, 如果省略, 则默认为…

Nginx安装以及LVS-DR集群搭建

Nginx安装 1.环境准备 yum insatall -y make gcc gcc-c pcre-devel #pcre-devel -- pcre库 #安装openssl-devel yum install -y openssl-devel 2.tar安装包 3.解压软件包并创建软连接 tar -xf nginx-1.22.0.tar.gz -C /usr/local/ ln -s /usr/local/nginx-1.22.0/ /usr/local…

数组对象去重的几种方法

场景&#xff1a; let arrObj [{ name: "小红", id: 1 },{ name: "小橙", id: 1 },{ name: "小黄", id: 4 },{ name: "小绿", id: 3 },{ name: "小青", id: 1 },{ name: "小蓝", id: 4 } ]; 方法一&#xff1a;…

【PyTorch】nn.Conv2d函数详解

nn.Conv2d 是 PyTorch 中的一个卷积层&#xff0c;用于实现二维卷积操作 torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride1, padding0, dilation1, groups1, biasTrue, padding_modezeros, deviceNone, dtypeNone )参数解释 in_channels&#xff1a;输入的通…