实现简单聊天

管道通信

目的: 实现 xxz 与 zy 之间的通讯聊天

功能: 同一网络下进行的模拟通讯实现

缺点:没有涉及到网络的通信,只是简单的进程之间模拟的通信

采用到的技术点:

  • 1 有名管道

    • 优点:
      • 在文件系统中作为一个特殊的文件而存在,但管道中的内容却存放在内存中。
  • 2 文件操作

  • 3 多进程创建与回收

  • 4 动态宏定义 【因为是写在一个程序中 模拟两个程序作用】

  • 5 文件描述符操作

  • 6 系统调用 open write

所需头文件:

#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <wait.h>  

步骤:

1 创建 两者通信 的管道

  • 使用mkfifo函数 作用: 创建有名管道

    所需头文件 :
    		#include <sys/types.h>
    		#include <sys/stat.h>
        参数:
        	 pathname:文件名
         	 mode:文件操作模式,一般用0666(所有用户可读可写)
        返回值:
         	 成功:0
          	 失败:-1,一般失败是因为存在与pathname名相同的文件
    

​ 实现:

	// 1.创建xxz给zy发信息的管道
    mkfifo("./xxz_to_zy",0666);
    // 2.创建zy给xxz发信息的管道
    mkfifo("./zy_to_xxz",0666);

在这里插入图片描述

2 创建两个进程用来收发消息

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <wait.h>
// 实现 xxz 与 zy之间的通信
int main(int argc, char const *argv[])
{
    // 1.创建xxz给zy发信息的管道
    mkfifo("./xxz_to_zy", 0666);
    // 2.创建zy给xxz发信息的管道
    mkfifo("./zy_to_xxz", 0666);
    // 3.创建子进程 一个用来发信息 一个用来收信息
    int i = 0;
    for (i = 0; i < 2; i++)
    {
        int pid = fork();
        if (pid == 0)
        {
            break;
        }
    }
    if (i == 0)//子进程1 用来发信息
    {   
    }
    else if (i == 1)//子进程2 用来收信息
    {
    }
    else if (i == 2)// 当前是父进程 用来回收子进程
    {
        while (waitpid(-1, NULL, WNOHANG) != -1);
    }
    return 0;
}
  • 3 动态的宏定义谁收谁发

    一共两个进程来处理

    那发的到底谁来发 用动态宏处理

    并且 open函数 属于系统调用 成功返回的是 最小文件描述符

    先写发信息:

    //子进程1 用来发信息
        if (i == 0)
        {   //文件描述符  0标准输入   1标准输出  2标准错误  
            int fd = 0;
            //如果有XXZ这个宏,当前用户就是 张优秀     
            #ifdef XXZ          
                fd = open("./xxz_to_zy", O_RDWR); //此时是张优秀给张十一发消息   此时是只读的
            #else
                fd = open("./zy_to_xxz", O_RDWR); //此时是张十一给张优秀发消息     
            #endif 
        }
    

    这样就会依据 不同的宏 来决定谁发送的

    开始写信息

    		//开始发信息   
            while (1)
            {
                // 用来存放信息 大小为300字节
                char info[300] = {0};  
                // 从标准输入中获取信息   最多获取300个字节
                fgets(info, 300, stdin);
                //打印展示 
                printf("我:%s", info);
                //清除脏数据 也就是按的回车上去的\n
                info[strlen(info) - 1] = 0;        
                //写进文件 消息
                write(fd,info,strlen(info));
                //给定结束的条件  使用 比较字符串是否相等
                if(strcmp(info,"88") == 0 )
                {
                    break;
                }
            }
            close(fd);
    

    完整的发送信息部分:

    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <wait.h>
    // 实现 张十一 与 张优秀 之间的通信
    int main(int argc, char const *argv[])
    {
        // 1.创建xxz给zy发信息的管道
        mkfifo("./xxz_to_zy", 0666);
        // 2.创建zy给xxz发信息的管道
        mkfifo("./zy_to_xxz", 0666);
        // 3.创建子进程 一个用来发信息 一个用来收信息
        int i = 0;
        for (i = 0; i < 2; i++)
        {
            int pid = fork();
            if (pid == 0)
            {
                break;
            }
        }
        //子进程1 用来发信息
        if (i == 0)
        {   //文件描述符  0标准输入   1标准输出  2标准错误  
            int fd = 0;
            //如果有XXZ这个宏,当前用户就是 张优秀     
            #ifdef XXZ          
                fd = open("./xxz_to_zy", O_RDWR); //此时是张优秀给张十一发消息   以可读、可写的方式打开
            #else
                fd = open("./zy_to_xxz", O_RDWR); //此时是张十一给张优秀发消息     
            #endif
            //开始发信息   
            while (1)
            {
                // 用来存放信息 大小为300字节
                char info[300] = {0};  
                // 从标准输入中获取信息   最多获取300个字节
                fgets(info, 300, stdin);
                //打印展示 
                printf("我:%s", info);
                //清除脏数据 也就是按的回车上去的\n
                info[strlen(info) - 1] = 0;        
                //写进文件 消息
                write(fd,info,strlen(info));
                //给定结束的条件  使用 比较字符串是否相等
                if(strcmp(info,"88") == 0 )
                {
                    break;
                }
            }
            close(fd);  
        }
        else if (i == 1)//子进程2 用来收信息
        {
            //接收信息  
        }
        else if (i == 2)// 当前是父进程 用来回收子进程
        {
            while (waitpid(-1, NULL, WNOHANG) != -1);
        }
        return 0;
    }
    

    动态宏定义写接收信息

     else if (i == 1)//子进程2 用来收信息
        {
            int fd = 0; 
            //接收信息  
            #ifdef XXZ
                fd = open("./zy_to_xxz",O_RDWR);   //读取 张十一发来的信息
            #else
                fd = open("./xxz_to_zy",O_RDWR);   //读取 张优秀发来的信息
            #endif
            //开始读取信息
            while(1)
            {
                // 用来存放信息 大小为300字节
                char buf[300] = {0};
                read(fd,buf,300);
                //再定义宏用来决定谁来说话
                #ifdef XXZ
                    printf("张优秀说:%s\n",buf);
                #else
                    printf("张十一说:%s\n",buf);
                #endif
                //给定结束的条件  使用 比较字符串是否相等    
                if(strcmp(buf,"88") == 0 )
                {   
                    break;
                }
            }
           close(fd);   //关闭文件描述符
        }
    

    运行效果:

    在这里插入图片描述

    完整代码:

    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <wait.h>
    int main(int argc, char const *argv[])
    {
        mkfifo("./xxz_to_zy", 0666);
        mkfifo("./zy_to_xxz", 0666);
        int i = 0;
        for (i = 0; i < 2; i++)
        {
            int pid = fork();
            if (pid == 0)
            {
                break;
            }
        }
        if (i == 0)
        {
            int fd = 0;
    	#ifdef XXZ
            fd = open("./xxz_to_zy", O_RDWR);
    	#else
            fd = open("./zy_to_xxz", O_RDWR);
    	#endif
            while (1)
            {
                char info[300] = {0};
                fgets(info, 300, stdin);
                printf("我:%s", info);
                info[strlen(info) - 1] = 0;
                write(fd, info, strlen(info));
                if (strcmp(info, "88") == 0)
                {
                    break;
                }
            }
            close(fd);
        }
        else if (i == 1)
        {
            int fd = 0;
    	#ifdef XXZ
            fd = open("./zy_to_xxz", O_RDWR);
    	#else
            fd = open("./xxz_to_zy", O_RDWR);
    	#endif
            while (1)
            {
                char info[300] = {0};
                read(fd, info, 300);
    
    		#ifdef XXZ
                printf("张优秀说:%s\n", info);
    		#else
                printf("张十一说:%s\n", info);
    		#endif
                if (strcmp(info, "88") == 0)
                {
                    break;
                }
            }
            close(fd);
        }
        else if (i == 2)
        {
            while (waitpid(-1, NULL, WNOHANG) != -1);
        }
        return 0;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值