返回顶部

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

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


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

posted @ 2022-09-25 14:36  Zoya23  阅读(209)  评论(0编辑  收藏  举报