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

news2024/10/6 22:30:19

作业一:打开两个终端,要求实现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;
}
                                                                                        

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

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

相关文章

最佳路径优先搜索算法

本来想直接写A* 的&#xff0c;不过看完最佳路径优先搜索算法后觉得还是要先理解一下这个算法后才能更好的理解A* 算法&#xff0c;所以把这篇文章放到A* 前面。 基本概念 最佳优先搜索算法&#xff08;Best-first-searching&#xff09;是一种启发式搜索算法&#xff08;Heu…

element vue2 动态添加 select+tree

难点在 1 添加一组一组的渲染 是往数组里push对象 循环的&#xff1b;但是要注意对象的结构! 因为这涉及到编辑完成后&#xff0c;表单提交时候的 校验&#xff01; 是校验每一个select tree里边 是否勾选 2 是在后期做编辑回显的时候 保证后端返回的值 是渲染到 select中的tr…

Markdown系列之Flowchat流程图

一.欢迎来到我的酒馆 介绍Markdown的Flowchart流程图语法。 目录 一.欢迎来到我的酒馆二.什么是Flowchart三.更进一步 二.什么是Flowchart 2.1 Flowchart是一款基于javascript的工具&#xff0c;使用它可以用代码创建简单的流程图。具体信息可以查看flowchart官网&#xff1a;…

vscode 设置滑条颜色

1. 默认的滑条是灰黑色的&#xff0c;很难看的清 2. 左下角&#xff0c;打开VS Code 设置功能 3. 输入命令 workbench color&#xff0c;回车 4. 找到工作台&#xff1a;自定义颜色设置&#xff0c;打开设置文件 setting.json 5. 打开配置文件 6. 添加颜色配置 "workben…

【C++】开源:事件驱动网络库libevent配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍事件驱动库libevent配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xf…

C++——STL容器【priority_queue】模拟实现

本章代码&#xff1a;优先级队列模拟实现、priority_queue文档 文章目录 &#x1f408;1. priority_queue介绍&#x1f984;2. priority_queue模拟实现&#x1f427;2.1 构造函数&#x1f427;2.2 建堆向下调整向上调整 &#x1f427;2.3 仿函数&#x1f427;2.4 push & po…

通向架构师的道路之漫谈使用ThreadLocal改进你的层次的划分

一、什么是ThreadLocal 早在JDK 1.2的版本中就提供java.lang.ThreadLocal&#xff0c;ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。 ThreadLocal很容易让人望文生义&#xff0c;想当然地认为是一个“本地线…

MapTR论文笔记

MAPTR: STRUCTURED MODELING AND LEARNING FOR ONLINE VECTORIZED HD MAP CONSTRUCTION 目的 传统高精地图 通过一些离线的基于 SLAM 的方法生成&#xff0c;需要复杂的流程以及高昂的维护费用。基于 bev 分割的建图方法&#xff0c;缺少向量化 实例级的信息&#xff0c;比如…

SPM(Swift Package Manager)开发及常见事项

SPM怎么使用的不再赘述&#xff0c;其优点是Cocoapods这样的远古产物难以望其项背的&#xff0c;而且最重要的是可二进制化、对xcproj项目无侵入&#xff0c;除了网络之外简直就是为团队开发的项目库依赖最好的管理工具&#xff0c;是时候抛弃繁杂低下的cocoapods了。 一&…

如何使用 ChatGPT 规划家居装修

你正在计划家庭装修项目&#xff0c;但不确定从哪里开始&#xff1f;ChatGPT 随时为你提供帮助。从集思广益的设计理念到估算成本&#xff0c;ChatGPT 可以简化你的家居装修规划流程。在本文中&#xff0c;我们将讨论如何使用 ChatGPT 有效地规划家居装修&#xff0c;以便你的项…

vue diff 前后缀+最长递增子序列算法

文章目录 查找相同前后缀通过前后缀位置信息新增节点通过前后缀位置信息删除节点 中间部份 diff判断节点是否需要移动删除节点删除未查找到的节点删除多余节点 移动和新增节点最长递增子序列 求解最长递增子序列位置信息 查找相同前后缀 如上图所示&#xff0c;新旧 children 拥…

SCT82A30DHKR_5.5V-100V Vin同步降压控制器

SCT82A30是一款100V电压模式控制同步降压控制器&#xff0c;具有线路前馈。40ns受控高压侧MOSFET的最小导通时间支持高转换比&#xff0c;实现从48V输入到低压轨的直接降压转换&#xff0c;降低了系统复杂性和解决方案成本。如果需要&#xff0c;在低至6V的输入电压下降期间&am…

Photoshop 2023 25.0beta「Mac」

Photoshop 2023是一款专业图像处理软件&#xff0c;它主要用于图像编辑、合成和设计等方面。 Photoshop beta创新式填充的功能特色包括&#xff1a; 自动识别和删除对象&#xff1a;该功能可以自动识别图像中的对象&#xff0c;并用周围的图像填充空白部分&#xff0c;使图像看…

window系统下 tinymce富文本编辑器在搜狗输入法下placeholder不消失现象

window 搜狗输入法下编辑器占位符和内容重叠问题 这种情况是&#xff0c;tinymce插件库存在一些兼容BUG&#xff0c;需要我们自行手写样式或者js替换掉placeholder&#xff0c;代码如下&#xff1a; // 获取富文本框的内容const handleChange (editorContent) > {// cons…

C++11 新特性 ---- final 和 override

一、final C中增加了final关键字&#xff0c;作用如下&#xff1a; ① 限制某个类不能被继承② 或者某个虚函数不能被重写 ① 限制某个类不能被继承 // ① 限制某个类不能被继承,也就是说这个类不能有派生类 class Base{ public:virtual void print() {cout<<"Ba…

电商数据获取:网络爬虫还是付费数据接口?

随着电商行业的迅速发展&#xff0c;对电商数据的需求也越来越大。在获取电商数据时&#xff0c;常常面临一个选择&#xff1a;是自己编写网络爬虫进行数据爬取&#xff0c;还是使用现有的付费数据接口呢&#xff1f;本文将从成本、可靠性、数据质量等多个角度进行分析&#xf…

【css】组合器

组合器是解释选择器之间关系的某种机制。在简单选择器器之间&#xff0c;可以包含一个组合器&#xff0c;从而实现简单选择器难以达到的效果。 CSS 中有四种组合器&#xff1a; 后代选择器 (空格)&#xff1a;匹配属于指定元素后代的所有元素&#xff0c;示例&#xff1a;div …

element-ui表格数据为空,图片占位提示

当表格的绑定数据为空时常需要显示暂无数据等字样&#xff0c;这时候就用到了empty-text <el-table:data"tableData"stripeborderempty-text"暂无数据"> 但&#xff0c;当数据为空&#xff0c;想用图片展示呢&#xff0c;如下图 方法一&#xff1a…

java.lang.UnsupportedClassVersionError TestCase

JavaFramework-JDK6.jar 放到JDK17运行没有问题 JavaFramework源码放到JDK17环境下编译出来的JavaFramework-JDK17.jar JavaFramework-JDK17.jar 放到JDK17运行没有问题 JavaFramework-JDK17.jar 放到JDK8运行没有问题&#xff0c;这个好像不对啊&#xff0c;可能之前编译设置…

day39反转字符串总结

反转字符串原理其实就是交换位置&#xff0c;以中间为分隔点&#xff1b; 基本套路&#xff1a;遍历前一般字符&#xff0c;互换位置&#xff1b; for循环模板 void reverseString(char* s, int sSize){char temp;for (int i 0, j sSize - 1; i < sSize/2; i, j--) {temp…