【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)//子进程发送   fifo
    {
        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;
            }
            //当管道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、管道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)//子进程接收  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;
}
                                                                                           

结果

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 88e6320收发器是一种高速以太网收发器解决方案,适用于高性能计算、网络存储和服务器应用。它采用单个IEEE 802.3ab 1000BASE-T物理接口,支持最高千兆位传输速率。 该收发器还具有自适应均衡和时钟数据恢复(ACD)技术,以支持最大100m的电缆长度和更稳定的数据传输。此外,88e6320还支持流控制和精确时间协议(PTP),以实现更高的通信可靠性和准确性。 与其他收发器相比,88e6320还具有独特的“GreenPHY”技术,可实现节能模式,降低系统功耗。因此,88e6320收发器是一种高效,可靠,且节能的网络通信解决方案。 ### 回答2: 88E6320是一款高速以太网收发器芯片,主要用于工业应用、数据心和企业级网络。该芯片支持各种数据速率,从10Mbps到10Gbps不等。此外,它也支持60W PoE(Power over Ethernet),可为设备供电,同时传输数据。 具体来说,88E6320具有多种接口,包括RGMII、SGMII和XFI,这使得它能够连接到不同类型的处理器和网络交换机。此外,该芯片配备了先进的自适应等化、时钟恢复和高级错误修正功能,以确保高速和可靠的数据传输。 该芯片还可以支持多种高级特性,如VLAN、QoS、流控制和媒体转发。这些特性可实现更加灵活和可管理的网络,以满足各种应用场景的需求。 总之,88E6320是一款功能强大、高性能的收发器芯片,能够满足广泛的工业和企业级网络需求。 ### 回答3: 88e6320是一种高速网络收发器,它主要被广泛应用于局域网(LAN)和广域网(WAN)等多种网络环境。该收发器采用高性能的SerDes技术,能够实现千兆级别的数据传输速率,具有很高的性能和稳定性。 88e6320收发器还采用了极佳的电磁干扰(EMI)和抗击穿(ESD)特性,可以有效地防止因信号干扰或静电放电而导致的网络故障和数据损坏。同时,该收发器还支持多种物理层协议,如千兆以太网、快速以太网、百兆以太网等,具有良好的兼容性和可靠性。 除此之外,该收发器还具有灵活的驱动接口和丰富的功能配置,可以根据实际需求进行灵活的配置和扩展。它还支持媒体独立协议(MII)和媒体独立接口(MDI),使得它可以与多种不同类型的PHY芯片和MAC层设备进行兼容和连接。 总之,88e6320收发器是一种性能卓越、稳定可靠的高速网络收发器,在现代网络应用具有广泛的应用前景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值