Linux中使用 有名管道 实现聊天功能 [Linux高并发服务器开发]

目录

一、实现的思路如下图:

二、代码实现

三、总结


一、实现的思路如下图:

因为从有名管道中读取不到数据,read会阻塞,所以需要分别在不同的进程中区读写。 对进程A创建 子进程去读管道数据; 对进程B,创建子进程去写管道数据。

二、代码实现

mychatA.c代码如下:

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

int main() {

    pid_t pid = fork();
    int fdw;
    int fdr;

    if(pid >0)
    {
        // 1.判断有名管道文件是否存在
        int ret = access("fifo1", F_OK);
        if(ret == -1) {
            // 文件不存在
            printf("管道不存在,创建对应的有名管道\n");
            ret = mkfifo("fifo1", 0664);
            if(ret == -1) {
                perror("mkfifo");
                exit(0);
            }
        }

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

        char buf[128];

        // 3.循环的写读数据
        while(1) {
            memset(buf, 0, sizeof(buf));
            // 获取标准输入的数据
            fgets(buf, 128, stdin);
            // 写数据
            ret = write(fdw, buf, strlen(buf));
            if(ret == -1) {
                perror("write");
                exit(0);
            }
        }


    }else if(pid ==0)
    {
        // 1.判断有名管道文件是否存在
        int ret = access("fifo2", F_OK);
        if(ret == -1) {
            // 文件不存在
            printf("管道不存在,创建对应的有名管道\n");
            ret = mkfifo("fifo2", 0664);
            if(ret == -1) {
                perror("mkfifo");
                exit(0);
            }
        }
        // 2.以只读的方式打开管道fifo2
        fdr = open("fifo2", O_RDONLY);
        if(fdr == -1) {
            perror("open");
            exit(0);
        }
        printf("打开管道fifo2成功,等待读取...\n");

        char buf[128];

        // 3.循环的读数据
        while(1) {
            // 5.读管道数据
            memset(buf, 0, sizeof(buf));
            int ret = read(fdr, buf, 128);
            if(ret <= 0) {
                perror("read");
                break;
            }
            printf("Message from B: %s\n", buf);
        }


    }else{
        perror("fork");
        exit(0);
    }

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

    return 0;
}

mychatB.c代码如下:

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

int main() {

    pid_t pid = fork();
    int fdw;
    int fdr;

    if(pid >0)
    {
        // 1.判断有名管道文件是否存在
        int ret = access("fifo1", F_OK);
        if(ret == -1) {
            // 文件不存在
            printf("管道不存在,创建对应的有名管道\n");
            ret = mkfifo("fifo1", 0664);
            if(ret == -1) {
                perror("mkfifo");
                exit(0);
            }
        }

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

        char buf[128];

        // 3.循环的读数据
        while(1) {
            // 读管道数据
            memset(buf, 0, sizeof(buf));
            ret = read(fdr, buf, 128);
            if(ret <= 0) {
                perror("read");
                break;
            }
            printf("message from A: %s\n", buf);
        }

    }else if(pid == 0)
    {
        // 1.判断有名管道文件是否存在
        int ret = access("fifo2", F_OK);
        if(ret == -1) {
            // 文件不存在
            printf("管道不存在,创建对应的有名管道\n");
            ret = mkfifo("fifo2", 0664);
            if(ret == -1) {
                perror("mkfifo");
                exit(0);
            }
        }

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

        char buf[128];

        // 3.循环的写数据
        while(1) {
            memset(buf, 0, sizeof(buf));
            // 获取标准输入的数据
            fgets(buf, 128, stdin);
            // 写数据
            int ret = write(fdw, buf, strlen(buf));
            if(ret == -1) {
                perror("write");
                exit(0);
            }
        }

    }else{
        perror("fork");
        exit(0);
    }

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

    return 0;
}

编译执行:

三、总结

使用有名管道来实现进程间通信,缺点是 对数据的长度是有要求限制的,因为管道的缓冲区大小是固定的。   使用socket套接字就没有这种限制。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值