实现简单聊天

news2025/1/11 4:05:01

管道通信

目的: 实现 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;
    }
    

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

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

相关文章

c++修炼之路之特殊类设计与类型转换

目录 一&#xff1a;特殊类设计 1.设计一个不能被拷贝的类 2.设计一个只能在堆上创建对象的类 3.设计一个只能在栈上创建对象的类 4.设计一个不能被继承的类 5.设计一个只能创建一个对象的类(单例模式) 二&#xff1a;c的类型转换 1.自定义类型&#xff0c;内置类型…

计算机的错误计算(八十五)

摘要 计算机的错误计算&#xff08;八十一&#xff09;至&#xff08;八十四&#xff09;介绍了双曲正弦、余弦、正割以及余割函数的计算精度问题。本节说明导致这些计算错误的主要原因。 首先&#xff0c;双曲正弦、余弦、正割以及余割函数主要包括 与 的计算&#xff0c;以…

逐行讲解Transformer的代码实现和原理讲解:nn.Linear线性层原理

视频详细讲解&#xff1a;LLM模型&#xff1a;代码讲解Transformer运行原理(1)_哔哩哔哩_bilibili 1 概述 经过Transformer的12个块处理完之后&#xff0c;4批文本数据得到了一个矩阵[4, 8, 16]&#xff0c;也就是每批数据都训练出了一个结果&#xff0c;在训练阶段&#xff…

Netty系列-3 ChannelFuture和ChannelPromise介绍

背景 Netty源码中大量使用了Future和Promise&#xff0c;学习ChannelFuture和ChannelFuture有助于理解Netty的设计思路。 本文的重点内容在于梳理清楚这些类的关系以及结合源码实现介绍这些类的作用&#xff0c;其中核心逻辑在于DefaultPromise和DefaultChannelPromise&#x…

GBase8sV8.8安装指南

目录 一、下载 Gbase 安装包二、安装预置条件1.确保安装包和平台适配2.安装依赖包&#xff1a;jdk(1.6版本以上)、unzip、libaio、libgcc、libstdc、ncurses、pam&#xff0c;如果缺失请提前安装 三、上传包并解压四、安装五、登录并创建数据库六、启动停止数据库七、常见问题八…

虚拟机ubuntu与主机共享文件夹

现在主机&#xff08;windows&#xff09;上新建一个共享文件夹 打开虚拟机 按下面操作打开共享文件夹 进入虚拟机的系统 cd /mnt/hgfs 如果报错 可以按下面的解决 挂载一下 sudo mount -t fuse.vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other 如果显示不存在这个文…

session机制

场景&#xff1a;当众多用户访问网站&#xff0c;发出HTTP请求&#xff0c;那么网站是如何判断哪个HTTP请求对应的是哪个用户 &#xff1f; 作用&#xff1a;用于服务端区分用户。 当用户使用客户端登录时&#xff0c;服务端会进行验证&#xff0c;验证通过后会为这次登录创建…

剖析Cookie的工作原理及其安全风险

Cookie的工作原理主要涉及到HTTP协议中的状态管理。HTTP协议本身是无状态的&#xff0c;这意味着每次请求都是独立的&#xff0c;服务器不会保留之前的请求信息。为了在无状态的HTTP协议上实现有状态的会话&#xff0c;引入了Cookie机制。 1. Cookie定义 Cookie&#xff0c;也…

EMC测试

传导干扰测试&#xff1a; 现场实录CE传导骚扰电压测试&#xff0c;硬件环境&#xff1a; R&S EPL1000 EMI测量接收机&#xff08;支持时域测试&#xff09; R&S ENV216人工电源网络 R&S ELEKTRA 测试软件 黑色底板&#xff0c;不写丝印&#xff0c;0402封装平行排…

Tomcat服务详解

一、部署Tomcat服务器 JDK安装官方网址&#xff1a;https://www.oracle.com/cn/java Tomcat安装官方网址&#xff1a;Apache Tomcat - Welcome! 安装JDK 1.获取安装包 wget https://download.oracle.com/otn/java/jdk/8u411-b09/43d62d619be4e416215729597d70b8ac/jdk-8u41…

【工程测试技术】第13章 流体参量测量

目录 第13章 流体参量测量 13.1压力的测量 13.1.1 弹性式压力敏感元件 1. 波登管 2. 膜片和膜盒 3. 波纹管 13.1.2 常用压力传感器 1. 应变式压力传感器 2. 压阻式压力传感器 3. 压电式压力传感器 4. 电容式压力传感器 5. 谐振式压力传感器 6. 位移式压力传感器 (1)…

整型数组按个位值排序

题目描述 给定一个非空数组(列表)&#xff0c;其元素数据类型为整型&#xff0c;请按照数组元素十进制最低位从小到大进行排序&#xff0c;十进制最低位相同的元司 相对位置保持不变。 当数组元素为负值时&#xff0c;十进制最低位等同于去除符号位后对应十进制值最低位。 输…

吐血整理 ChatGPT 3.5/4.0 新手使用手册~ 【2024.09.04 更新】

以前我也是通过官网使用&#xff0c;但是经常被封号&#xff0c;就非常不方便&#xff0c;后来有朋友推荐国内工具&#xff0c;用了一阵之后&#xff0c;发现&#xff1a;稳定方便&#xff0c;用着也挺好的。 最新的 GPT-4o、4o mini&#xff0c;可搭配使用~ 1、 最新模型科普&…

VisualStudio环境搭建C++

Visual Studio环境搭建 说明 C程序编写中&#xff0c;经常需要链接头文件(.h/.hpp)和源文件(.c/.cpp)。这样的好处是&#xff1a;控制主文件的篇幅&#xff0c;让代码架构更加清晰。一般来说头文件里放的是类的申明&#xff0c;函数的申明&#xff0c;全局变量的定义等等。源…

Java面试题·解释题·框架部分

系列文章目录 Java面试题解释题总体概括 Java面试题解释题JavaSE部分 Java面试题解释题框架部分 文章目录 系列文章目录前言一、MyBatis1. 请你介绍MyBatis框架2. MyBatis框架的核心思想是什么&#xff1f;3. MyBatis的核心配置文件中常用的子标签有哪些&#xff1f;4. mapper…

饲料加工机器设备有哪些组成部分

在快速发展的畜牧业中&#xff0c;饲料加工作为支撑养殖业的重要环节&#xff0c;其效率与品质直接影响着养殖业的成本效益与动物健康。随着科技的进步&#xff0c;饲料加工机器设备也在不断升级&#xff0c;为养殖行业带来了变革。一、智能化粉碎机&#xff1a;细度可调&#…

Unity Adressables 使用说明(五)在运行时使用 Addressables(Use Addressables at Runtime)

一旦你将 Addressable assets 组织到 groups 并构建到 AssetBundles 中&#xff0c;就需要在运行时加载、实例化和释放它们。 Addressables 使用引用计数系统来确保 assets 只在需要时保留在内存中。 Addressables 初始化 Addressables 系统在运行时第一次加载 Addressable …

SimD:基于相似度距离的小目标检测标签分配

摘要 https://arxiv.org/pdf/2407.02394 由于物体尺寸有限且信息不足&#xff0c;小物体检测正成为计算机视觉领域最具挑战性的任务之一。标签分配策略是影响物体检测精度的关键因素。尽管已经存在一些针对小物体的有效标签分配策略&#xff0c;但大多数策略都集中在降低对边界…

怎么利用XML发送物流快递通知短信

现如今短信平台越来越普遍了&#xff0c;而短信通知也分很多种&#xff0c;例如服务通知、订单通知、交易短信通知、会议通知等。而短信平台在物流行业通知这一块作用也很大。在家时:我们平时快递到了&#xff0c;如果电话联系不到本人&#xff0c;就会放到代收点&#xff0c;然…

正负极层数更新器

文件名&#xff1a;dcs_tkinter.py import tkinter as tk from tkinter import messagebox import redis# 连接Redis r redis.Redis(hostlocalhost, port6379, db0)def update_redis_and_display():try:# 从输入框获取值positive_layers int(entry_positive.get())negative_…