【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__);

	//以写的方式打开管道1
	int fd_w=open("./fifo",O_WRONLY);
	if(fd_w < 0)
	{
		perror("open");
		return -1;
	}
	printf("open pipeA success __%d__\n",__LINE__);
	//以读的方式打开管道B
	int 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改成\0
		if((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、管道2
	close(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__);
	
	//以读的方式打开管道1
	int fd_r=open("./fifo",O_RDONLY);
	if(fd_r < 0)
	{
		perror("open");
		return -1;
	}
	printf("open pipe1 success __%d__\n",__LINE__);
	//以写的方式打开管道2
	int 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终端输入的是否是quit
		if(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();

    //以写的方式打开管道1
    int fd_w=open("./fifo",O_WRONLY);
    if(fd_w < 0)
    {
        perror("open");
        return -1;
    }
    printf("open pipeA success __%d__\n",__LINE__);
    //以读的方式打开管道B
    int 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)//子进程发送
    {
        while(1)
        {
            //管道1操作(写入数据)
            fgets(buf,sizeof(buf),stdin);    //从终端获取数据

            buf[strlen(buf)-1] = '\0';   //将\n改成\0
            if((write(fd_w,buf,sizeof(buf))) < 0)  //将字符串写进管道A  
            {
                perror("write");
                return -1;
            }
            printf("A: %s\n",buf);
            //当管道1的读段关闭,管道1的写段尝试写入数据,则管道破裂,退出进程
            //c=strcmp(buf,"quit\n");//将读到的数据与quit比较
            if(strncmp(buf,"quit",4) == 0)//如果相同,c为0,达到退出条件,可以退出循环
            {
                break;
            }
            //printf("写入数据成功 res=%ld\n",res);
        }
        close(fd_w);
        exit(0);
    }
    else if(cpid > 0)//父进程接收
    {
        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个数据`
            {
                printf("对方进程退出\n");
                break;
            }
            //打印从管道2中读取到的数据
            printf("B:%s\n",buf);
        }
        wait(NULL);
        close(fd_r);
    }

    //关闭管道1、管道2
    close(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();

    //以读的方式打开管道1
    int fd_r=open("./fifo",O_RDONLY);
    if(fd_r < 0)
    {
        perror("open");                                                                  
        return -1;
    }
    printf("open pipe1 success __%d__\n",__LINE__);
    //以写的方式打开管道2
    int 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)//子进程接收
    {
        while(1)
        {
            //管道1操作(读取数据)
            bzero(buf,sizeof(buf));
            res=read(fd_r,buf,sizeof(buf));

            if(res < 0)
            {
                perror("read");
                return -1;
            }
            if(0 == res )
            {
                printf("对方进程退出\n");
                break;
            }
            printf("A:%s\n",buf);
        }
        close(fd_r);
        exit(0);
    }
    else if(cpid > 0)//父进程发送
    {
        while(1)
        {
            //管道2操作(写入数据)
            printf("B: ");
            fgets(buf,sizeof(buf),stdin);
            buf[strlen(buf)-1] = '\0';
            if((write(fd_w,buf,sizeof(buf))) < 0)
            {
                perror("write");
                return -1;
            }
            //当管道2关闭,管道2的写段尝试写入数据,则管道破裂,退出进程
            //c=strcmp(buf,"quit");
            if(strncmp(buf,"quit",4) == 0)//判断B终端输入的是否是quit
            {
                break;
            }
        }
        close(fd_w);
        wait(NULL);
    }
    else
    {
        perror("fork");
        return -1;
    }

    close(fd_r);
    close(fd_w);
    return 0;
}
                                                                                        

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Docker】DockerFile

目录 一、镜像原理 二、如何制作镜像 1、容器转镜像 2、DockerFile 三、DockerFile关键字​编辑 四、案例&#xff1a;部署SpringBoot项目 一、镜像原理 docker镜像是由一个特殊的文件系统叠加而成的&#xff0c;他的最低端是bootfs&#xff0c;并使用宿主机的bootfs&…

FPGA优质开源项目 – PCIE通信

本文介绍一个FPGA开源项目&#xff1a;PCIE通信。该工程围绕Vivado软件中提供的PCIE通信IP核XDMA IP建立。Xilinx提供了XDMA的开源驱动程序&#xff0c;可在Windows系统或者Linux系统下使用&#xff0c;因此采用XDMA IP进行PCIE通信是比较简单直接的。 本文主要介绍一下XDMA I…

继承(Inheritance)

Odoo的一个强大方面是它的模块化。模块专用于业务需求&#xff0c;但模块也可以相互交互。这对于扩展现有模块的功能非常有用。例如&#xff0c;在我们的房地产场景中&#xff0c;我们希望在常规用户视图中直接显示销售人员的财产列表。 在介绍特定的Odoo模块继承之前&#xf…

卸载本机已安装的node.js(v.16.13.0版本)

因为要用多版本的node&#xff0c;准备安装一个nvm管理&#xff0c;所以需要先卸载掉原来安装的v.16.13.0版本。 记录一下卸载过程 1、在系统设置-应用里卸载node 妈蛋这样卸载报错。。找了下根本没有这个路径 那就只能最简单的方法了&#xff0c;全部删掉 1、删除node的安装…

pygame贪吃蛇游戏

pygame贪吃蛇游戏 贪吃蛇游戏通过enter键启动&#xff0c;贪吃蛇通过WSAD进行上下左右移动&#xff0c;每次在游戏区域中随机生成一个食物&#xff0c;每次吃完食物后&#xff0c;蛇变长并且获得积分&#xff1b;按空格键暂停。 贪吃蛇 import random, sys, time, pygame from …

[CKA]考试之PersistentVolumeClaims

由于最新的CKA考试改版&#xff0c;不允许存储书签&#xff0c;本博客致力怎么一步步从官网把答案找到&#xff0c;如何修改把题做对&#xff0c;下面开始我们的 CKA之旅 题目为&#xff1a; Task 创建一个名字为pv-volume的pvc&#xff0c;指定storageClass为csi-hostpath-…

大模型使用——超算上部署LLAMA-2-70B-Chat

大模型使用——超算上部署LLAMA-2-70B-Chat 前言 1、本机为Inspiron 5005&#xff0c;为64位&#xff0c;所用操作系统为Windos 10。超算的操作系统为基于Centos的linux&#xff0c;GPU配置为A100&#xff0c;所使用开发环境为Anaconda。 2、本教程主要实现了在超算上部署LLAM…

MySQL — InnoDB事务

文章目录 事务定义事务特性事务隔离级别READ UNCOMMITTEDREPEATABLE READREAD COMMITTEDSERIALIZABLE 事务存在的问题脏读&#xff08;Dirty Read&#xff09;不可重复读&#xff08;Non-repeatable Read&#xff09;幻读&#xff08;Phantom Read&#xff09; 事务定义 数据库…

零代码爬虫平台SpiderFlow的安装

什么是 Spider Flow &#xff1f; Spider Flow 是一个高度灵活可配置的爬虫平台&#xff0c;用户无需编写代码&#xff0c;以流程图的方式&#xff0c;即可实现爬虫。该工具支持多数据源、自动保存至数据库、任务监控、抓取 JS 动态渲染页面、插件扩展&#xff08;OCR 识别、邮…

Windows下安装Scala(以Scala 2.11.12为例)

Windows下安装Scala&#xff08;以Scala 2.11.12为例&#xff09; 一、Scala2.11.12官网下载二、Scala2.11.12网盘下载三、Scala各版本下载地址四、Scala安装4.1、点击 scala-2.11.12.msi 文件安装4.2、设置环境变量 %SCALA_HOME%4.3、环境变量Path添加条目%SCALA_HOME%\bin 四…

【云原生】使用kubeadm搭建K8S

目录 一、Kubeadm搭建K8S1.1环境准备1.2所有节点安装docker1.3所有节点安装kubeadm&#xff0c;kubelet和kubectl1.4部署K8S集群1.5所有节点部署网络插件flannel 二、部署 Dashboard 一、Kubeadm搭建K8S 1.1环境准备 服务器IP配置master&#xff08;2C/4G&#xff0c;cpu核心…

Vue系列第八篇:echarts绘制柱状图和折线图

本篇将使用echarts框架进行柱状图和折线图绘制。 目录 1.绘制效果 2.安装echarts 3.前端代码 4.后端代码 1.绘制效果 2.安装echarts // 安装echarts版本4 npm i -D echarts4 3.前端代码 src/api/api.js //业务服务调用接口封装import service from ../service.js //npm …

Jenkins触发器时间、次数设定

触发器触发条件介绍 触发器触发条件公式&#xff1a;由5颗星组成 * * * * * 分别代表&#xff1a;分钟(0-59) 小时(0-23) 日期(1-31) 月份(1-12) 星期(0-6) 企业项目中常用场景介绍 场景1&#xff1a;接口脚本部分测试通过&#xff0c;部分还在进行&#xff0c;回归测试脚本执行…

数学知识(三)

一、容斥原理 #include<iostream> #include<algorithm>using namespace std;const int N 20;typedef long long LL; int n,m; int p[N];int main() {cin>>n>>m;for(int i 0;i < m;i ) cin>>p[i];int res 0;//从1枚举到2^m(位运算)for(int …

数据结构---B树

目录标题 B-树的由来B-树的规则和原理B-树的插入分析B-树的插入实现准备工作find函数insert中序遍历 B-树的性能测试B-树的删除B树B树的元素插入B*树的介绍 B-树的由来 在前面的学习过程中&#xff0c;我们见过很多搜索结构比比如说顺序查找&#xff0c;二分查找&#xff0c;搜…

第三章 图论 No.1单源最短路及其综合应用

文章目录 1129. 热浪1128. 信使1127. 香甜的黄油1126. 最小花费920. 最优乘车903. 昂贵的聘礼1135. 新年好340. 通信线路342. 道路与航线341. 最优贸易 做乘法的最短路时&#xff0c;若权值>0&#xff0c;只能用spfa来做&#xff0c;相等于加法中的负权边 1129. 热浪 1129.…

码出高效_第二章 | 面向对象_上

目录 一. OOP理念1. 概念辨析2. 四大特性1. 抽象2. 封装3. 继承4. 多态 二. 初识Java1. JDKJDK 5-11的重要类、特性及重大改变 2. JRE关于JVM 三. 类1. 概述2. 接口和抽象类1. 概念及相同点2. 不同点3. 总结 3. 内部类4. 访问权限控制1. 由来2. public/private/无/private3. 推…

AI介绍——chat gpt/文心一言/claude/bard/星火大模型/bing AI

AI体验 1. AI 介绍&#xff08;注册和使用&#xff09;1.1 Chat GPT1.2 文心一言1.3 Slack 上的 Claude1.3.1 Claude 介绍1.3.2 Claude 使用 1.4 Google的Bard1.4.1 Bard 介绍1.4.2 Bard 使用 1.5 科大讯飞的星火大模型1.5.1 星火大模型 介绍1.5.2 星火大模型 使用 1.6 new bin…

UE4查看加密PAK里边的资源Android/iOS/PC方法

我们经常会需要把1个模型进行减面然后在移动端使用,有时候会出现移动端模型和PC端模型不一致的问题,这时候就需要将移动端的模型和PC端的模型进行对比,找到问题出现的原因,检查Mesh、Normal、UV0、UV1、MaterialId、碰撞等是否一致。 如何打包Pak文件,见这篇文章:UE4打包…

定点数源码除法运算补码除数运算

恢复余数法 加减交替法 补码除法