首页 > 系统相关 >【Linux】有名管道实现进程间通信——一个简单聊天程序

【Linux】有名管道实现进程间通信——一个简单聊天程序

时间:2022-09-25 14:46:05浏览次数:44  
标签:int fifo2 fifo1 ret 间通信 聊天 Linux include buf

有名管道实现简单聊天程序


1. "你来我往"式简单聊天

函数功能:简单聊天程序,两个程序abab发送信息,b接收信息,ba发送信息,a接收信息;...

image

源码参考:
chatA.c

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

int main()
{
    char *fifo1 = "fifo1";
    char *fifo2 = "fifo2";

    // 1. 判断有名管道文件是否存在
    int ret = access(fifo1, F_OK);
    if (ret == -1)
    {
        // 文件不存在,需要创建
        printf("%s文件不存在,创建管道\n", fifo1);
        ret = mkfifo(fifo1, 0664);
        if (ret == -1)
        {
            perror("mkfifo");
            exit(-1); // 退出
        }
    }

    ret = access(fifo2, F_OK);
    if (ret == -1)
    {
        // 文件不存在,需要创建
        printf("%s文件不存在,创建管道\n", fifo2);
        ret = mkfifo(fifo2, 0664);
        if (ret == -1)
        {
            perror("mkfifo");
            exit(-1); // 退出
        }
    }

    // 2. 以只写方式打开管道1

    int fdw = open(fifo1, O_WRONLY);
    if (fdw == -1)
    {
        perror("open");
        exit(-1);
    }

    printf("只写方式打开fifo1成功,等待写入数据...\n");

    // 以只读方式打开管道2
    int fdr = open(fifo2, O_RDONLY);
    if (fdr == -1)
    {
        perror("open");
        exit(-1);
    }
    printf("只读方式打开fifo2成功,等待读取数据...\n");

    // 3. 循环写读数据
    char buf[256];
    while (1)
    {
        memset(buf, 0, sizeof(buf));
        // 获取标准输入的数据,使用fgets()函数
        fgets(buf, sizeof(buf), stdin);
        // 写数据到fifo1
        int len = write(fdw, buf, strlen(buf));
        if (len == -1)
        {
            perror("write");
            break;
        }

        // 读管道数据
        memset(buf, 0, sizeof(buf));
        len = read(fdr, buf, sizeof(buf));
        if (len <= 0)
        {
            perror("read");
            break;
        }
        printf("buf : %s\n", buf);
    }

    // 关闭文件描述符
    close(fdr);
    close(fdw);

    return 0;
}

chatB.c


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

int main()
{
    char *fifo1 = "fifo1";
    char *fifo2 = "fifo2";

    // 1. 判断有名管道文件是否存在
    int ret = access(fifo1, F_OK);
    if (ret == -1)
    {
        // 文件不存在,需要创建
        printf("%s文件不存在,创建管道\n", fifo1);
        ret = mkfifo(fifo1, 0664);
        if (ret == -1)
        {
            perror("mkfifo");
            exit(-1); // 退出
        }
    }

    ret = access(fifo2, F_OK);
    if (ret == -1)
    {
        // 文件不存在,需要创建
        printf("%s文件不存在,创建管道\n", fifo2);
        ret = mkfifo(fifo2, 0664);
        if (ret == -1)
        {
            perror("mkfifo");
            exit(-1); // 退出
        }
    }

    // 2. 以只读方式打开管道1
    int fdr = open(fifo1, O_RDONLY);
    if (fdr == -1)
    {
        perror("open");
        exit(-1);
    }
    printf("只读方式打开fifo1成功,等待读取数据...\n");

    // 以只写方式打开管道2
    int fdw = open(fifo2, O_WRONLY);
    if (fdw == -1)
    {
        perror("open");
        exit(-1);
    }
    printf("只写方式打开fifo2成功,等待写入数据...\n");

    // 3. 循环读写数据
    char buf[256];
    while (1)
    {
        // 读管道数据
        memset(buf, 0, sizeof(buf));
        int len = read(fdr, buf, sizeof(buf));
        if (len <= 0)
        {
            perror("read");
            break;
        }
        printf("buf : %s\n", buf);

        memset(buf, 0, sizeof(buf));
        // 获取标准输入的数据,使用fgets()函数
        fgets(buf, sizeof(buf), stdin);
        // 写数据到fifo1
        len = write(fdw, buf, strlen(buf));
        if (len == -1)
        {
            perror("write");
            break;
        }
    }

    // 关闭文件描述符
    close(fdr);
    close(fdw);

    return 0;
}

程序运行:


2. "喋喋不休"式简单聊天

上面的程序不能实现一方一直给另一方发送信息,可以把读写功能分别放在不同的进程中,比如放在父子进程中分别对读写进行操作。

image

参考代码:
newChatA.c


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

int main()
{
    // 1. 创建子进程
    pid_t pid = fork();

    if (pid > 0)
    {
        // 父进程, 写FIFO1
        char *fifo1 = "fifo1";
        // 2. 判断有名管道文件是否存在
        int ret = access(fifo1, F_OK);
        if (ret == -1)
        {
            // 文件不存在,需要创建
            printf("%s文件不存在,创建管道\n", fifo1);
            ret = mkfifo(fifo1, 0664);
            if (ret == -1)
            {
                perror("mkfifo");
                exit(-1); // 退出
            }
        }

        // 3. 以只写方式打开 FIFO1

        int fdw = open(fifo1, O_WRONLY);
        if (fdw == -1)
        {
            perror("open");
            exit(-1);
        }

        printf("只写方式打开fifo1成功,等待写入数据...\n");

        // 4. 循环写入数据
        char buf[256];
        while (1)
        {
            memset(buf, 0, sizeof(buf));
            // 获取标准输入的数据,使用fgets()函数
            fgets(buf, sizeof(buf), stdin);
            // 写数据到fifo1
            int len = write(fdw, buf, strlen(buf));
            if (len == -1)
            {
                perror("write");
                break;
            }
        }

        close(fdw);
    }
    else if (pid == 0)
    {
        // 子进程  读FIFO2
        char *fifo2 = "fifo2";

        int ret = access(fifo2, F_OK);
        if (ret == -1)
        {
            // 文件不存在,需要创建
            printf("%s文件不存在,创建管道\n", fifo2);
            ret = mkfifo(fifo2, 0664);
            if (ret == -1)
            {
                perror("mkfifo");
                exit(-1); // 退出
            }
        }

        // 以只读方式打开 FIFO2
        int fdr = open(fifo2, O_RDONLY);
        if (fdr == -1)
        {
            perror("open");
            exit(-1);
        }
        printf("只读方式打开fifo2成功,等待读取数据...\n");

        // 循环读数据
        char buf[256];
        while (1)
        {
            // 读管道数据
            memset(buf, 0, sizeof(buf));
            int len = read(fdr, buf, sizeof(buf));
            if (len <= 0)
            {
                perror("read");
                break;
            }
            printf("buf : %s\n", buf);
        }
        close(fdr);
    }

    return 0;
}

newChatB.c

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

int main()
{
    // 1. 创建子进程
    pid_t pid = fork();

    if (pid > 0)
    {
        // 父进程, 写FIFO2
        char *fifo2 = "fifo2";
        // 2. 判断有名管道文件是否存在
        int ret = access(fifo2, F_OK);
        if (ret == -1)
        {
            // 文件不存在,需要创建
            printf("%s文件不存在,创建管道\n", fifo2);
            ret = mkfifo(fifo2, 0664);
            if (ret == -1)
            {
                perror("mkfifo");
                exit(-1); // 退出
            }
        }

        // 3. 以只写方式打开 FIFO2

        int fdw = open(fifo2, O_WRONLY);
        if (fdw == -1)
        {
            perror("open");
            exit(-1);
        }

        printf("只写方式打开fifo2成功,等待写入数据...\n");

        // 4. 循环写入数据
        char buf[256];
        while (1)
        {
            memset(buf, 0, sizeof(buf));
            // 获取标准输入的数据,使用fgets()函数
            fgets(buf, sizeof(buf), stdin);
            // 写数据到fifo1
            int len = write(fdw, buf, strlen(buf));
            if (len == -1)
            {
                perror("write");
                break;
            }
        }

        close(fdw);
    }
    else if (pid == 0)
    {
        // 子进程  读FIFO1
        char *fifo1 = "fifo1";

        int ret = access(fifo1, F_OK);
        if (ret == -1)
        {
            // 文件不存在,需要创建
            printf("%s文件不存在,创建管道\n", fifo1);
            ret = mkfifo(fifo1, 0664);
            if (ret == -1)
            {
                perror("mkfifo");
                exit(-1); // 退出
            }
        }

        // 以只读方式打开 FIFO1
        int fdr = open(fifo1, O_RDONLY);
        if (fdr == -1)
        {
            perror("open");
            exit(-1);
        }
        printf("只读方式打开fifo1成功,等待读取数据...\n");

        // 循环读数据
        char buf[256];
        while (1)
        {
            // 读管道数据
            memset(buf, 0, sizeof(buf));
            int len = read(fdr, buf, sizeof(buf));
            if (len <= 0)
            {
                perror("read");
                break;
            }
            printf("buf : %s\n", buf);
        }
        close(fdr);
    }

    return 0;
}

程序运行:

image

标签:int,fifo2,fifo1,ret,间通信,聊天,Linux,include,buf
From: https://www.cnblogs.com/Zoya-/p/16727818.html

相关文章

  • Linux—用户与组
    Linux操作系统是多用户、多任务系统——即允许多个用户同时登录Linux系统并启动多个任务(有的用户是远程登陆)。用户账号和用户组是进行身份鉴定和权限控制的基础,身份鉴别的......
  • Linux基础
    1 Linux的思想1,一切皆文件;2、单一目的的小程序,组合小程序完成复杂任务;在linux中,每一个命令都是对应一个功能,通过不同的参数来完成不同的要求,通过繁多的小的命令来完成......
  • Linux—软链接、硬链接 vim
    软链接、硬链接​原理上,硬链接和源文件的inode节点号相同,两者互为硬链接。软连接和源文件的inode节点号不同,进而指向的block也不同,软连接block中存放了源文件的路径......
  • linux基本命令
    cd 切换文件夹cd/home绝对路径 以包目录开头cdadmin相对路径不以包目录开头cd..返回上级目录cd~到自己的家目录/home/admincd-电视会看功能pwd查看......
  • Linux—目录详解
    登录系统后,在当前命令窗口下输入命令:ls/会看到如图所示:![](https://img2022.cnblogs.com/blog/2595295/202209/2595295-20220925131352159-505699413.png)树状......
  • Linux常用命令(用户组管理命令)
    用户组管理命令每个用户都有一个用户组,系统可以对一个用户组中的所有用户进行集中管理。不同Linux系统对用户组的规定有所不同,如Linux下的用户属于与它同名的用户组,这......
  • Linux之Xshell
    shell简介shell的英文含义是“壳”;它是相对于内核来说的,因为它是建立在内核的基础上,面向于用户的一种表现形式,比如我们看到一个球,见到的是它的壳,而非核。Linux中的shell......
  • Linux常用基本命令(时间日期及用户管理类)
    时间日期类1)基本语法date [OPTION]...[+FORMAT]2)选项说明选项功能-d<时间字符串>显示指定的“时间字符串”表示的时间,而非当前时间-s<日期时间>设置......
  • Linux 安装 JDK
    Linux安装JDK1.上传jdk-8u141-linux-x64.tar.gz安装包#创建文件夹[root@node-01~]#mkdirapps#解压安装包[root@node-01~]#tar-xzvfjdk-8u141-linux-x6......
  • [oeasy]教您玩转linux0001 - 先跑起来
    Python什么是Python?Python很好用适合初学者而且在各个领域都很强大 ​ 添加图片注释,不超过140字(可选) 后来居上下图可以点......