利用有名管道实现进程间通信(聊天小程序)

/*
名称:利用有名管道实现进程间通信(聊天小程序)
说明:此程序,是利用有名管道实现进程间的相互通信。
关于有名管道,需要说的是,它是一个特殊的文件,因为它的名字会保存在文件系统中(inode节点,这也是其为什么能在无关进程间通信的原因吧)但是,它的内容并不是在内存中(无名管道的名字和内容都是放在内存中的)。
关于管道的建立,有一点要说明的就是一般来说,我们只需要把管道的打开方式设置成阻塞的(默认)的就可以,但是这个程序中,要把管道设置成非阻塞的(因为你也不知道对方什么时候会发给你,你什么时候会发送消息给对方)。在设置管道非阻塞的时候,需要用到一个新的函数,就是fcntl()(我把它叫做文件控制函数)。它可以把文件描述符所代表的文件流(此处是管道流)设置成非阻塞的。
其次,由于要双向通信,而命名管道一般用于单双工通信,所以需要两个管道。但是比较气人的是,由于种种原因(我也不清楚的原因)在设置打开非阻塞管道是时候,必须先打开读端,再打开写端,再打开写端,否则就会出错。由于这个原因,我们不能同时打开两个文件管道(因为在一个进程中需要以读方式打开一个管道,在以写方式打开一个管道),如果同时打开的话,会出错。为了解决这个问题,我让server首先打开pipe1的读端,然后一直监听是否有消息,如果有消息的话在打开另一个管道写端。这样的话,在运行程序的时候只能先让server程序先运行了。

*/

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

#include <fcntl.h> 



//初始化函数,用于非阻塞标准输入
int Init()
{
    if(-1 == fcntl(0,F_SETFL,O_NONBLOCK))
    {
        printf("fail to change the  std mode.\n");
        return -1;
    }


}

int main()
{
    int pipe_fd1,pipe_fd2;
    int read_cou = 0,write_cou = 0;
    char read_buf[100];
    char write_buf[100];
    memset(read_buf,'\0',sizeof(read_buf));
    memset(write_buf,'\0',sizeof(write_buf));

    //判断管道是否存在,如果不存在就创建有名管道
    if(-1 == access("pipe1",F_OK))
    {
        if(-1 == mkfifo("pipe1",0777))
        {
            printf("Could not create pipe1\n");
            return -1;
        }
    }

    if(-1 == access("pipe2",F_OK))
    {
        if(-1 == mkfifo("pipe2",0777))
        {
            printf("Could not create pipe2\n");
            return -1;
        }
    }

    //先打开一个管道,此管道用于server读,client写。非阻塞打开
    pipe_fd1 = open("pipe1",O_RDONLY | O_NONBLOCK);

    Init();


    //这个while循环用于检测是否有client提出访问请求(发来信息)
    while(1)
    {
        read_cou = read(pipe_fd1,read_buf,PIPE_BUF); //从管道中读取数据
        if(read_cou > 0)        
        {
            printf("receive client:%s\n",read_buf);
            pipe_fd2 = open("pipe2",O_WRONLY | O_NONBLOCK); //如果首次提出请求,则打开第二个管道用于server写,client读
            break;
        }


    }


    //正式交流信息阶段
    while(1)
    {
        //读出过程
        read_cou = read(pipe_fd1,read_buf,PIPE_BUF);
        if(read_cou > 0)
        {
            printf("server receive :%s\n",read_buf);
        }

        //从标准输入中读取,如果有输入再写入管道
        if (gets(write_buf) != NULL)
        {
            printf("server input:%s.\n",write_buf);
            write(pipe_fd2,write_buf,sizeof(write_buf));
        }

    }
    return 0;
}
//client端:
#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <fcntl.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <limits.h>  
#include <string.h>  

#include <fcntl.h> 

//初始化函数,用于非阻塞标准输入
int Init()
{
    if(-1 == fcntl(0,F_SETFL,O_NONBLOCK))
    {
        printf("fail to change the  std mode.\n");
        return -1;
    }


}

int main()
{
    int pipe_fd1,pipe_fd2;
    int read_cou = 0,write_cou = 0;
    char read_buf[100];
    char write_buf[100];
    memset(read_buf,'\0',sizeof(read_buf));
    memset(write_buf,'\0',sizeof(write_buf));

    //判断管道是否存在,如果不存在就创建有名管道
    if(-1 == access("pipe1",F_OK))
    {
        if(-1 == mkfifo("pipe1",0777))
        {
            printf("Could not create pipe1\n");
            return -1;
        }
    }

    if(-1 == access("pipe2",F_OK))
    {
        if(-1 == mkfifo("pipe2",0777))
        {
            printf("Could not create pipe2\n");
            return -1;
        }
    }

    //打开两个管道,其中pipe1用于server读,pipe2用于server写(非阻塞打开)
    pipe_fd1 = open("pipe1",O_WRONLY | O_NONBLOCK);
    pipe_fd2 = open("pipe2",O_RDONLY | O_NONBLOCK);

    Init();

    //此循环用于首先向server提出请求,是server打开第二个通信管道
    while(1)
    {
        //写入过程
        if (gets(write_buf) != NULL)
        {
            printf("client input:%s.\n",write_buf);
            write(pipe_fd1,write_buf,sizeof(write_buf));
            sleep(1);
            break;
        }
    }


    //和server正式通信
    while(1)
    {
        //读出过程
        read_cou = read(pipe_fd2,read_buf,PIPE_BUF);
        if(read_cou > 0)
        {
            printf("client receive :%s\n",read_buf);
        }

        //写入过程
        if (gets(write_buf) != NULL)
        {
            //从标准输入中读取,如果有输入再写入管道
            printf("client input:%s.\n",write_buf);
            write(pipe_fd1,write_buf,sizeof(write_buf));
        }   

    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值