• 命名管道实现进程间通信--石头、剪刀、布游戏 分类: linux 2014-06-01 22:50 467人阅读 评论(0) 收藏


    下面这个程序利用命名管道实现进程间通信,模拟石头剪刀布游戏。

    主进程为裁判进程,两个子进程为选手进程。裁判与选手间各建立一个命名管道。

    进行100次出招,最后给出游戏胜负。


    #include <unistd.h>
    #include<fcntl.h>
    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<errno.h>
    #include<stdlib.h>
    #include<string.h>
    #define FIFO1 "/tmp/myfifo1"
    #define FIFO2 "/tmp/myfifo2"
    #define SIZE 5
    #define COUNT 100
    int judge(char a,char b);
    int main(void) 
    { 
     int fp,fp1,fp2,i=1;
     int status;
     int nread;
     char buf[SIZE]={0};
     char c1[COUNT]={0};//用来存放p1发送的消息
     char c2[COUNT]={0};//用来存放p2发送的消息
     pid_t p1 = fork(); //产生子进程p1
     /*********************************/
     if(p1==0)
     { 
      srand(time(NULL));
      while((fp=open(FIFO1,O_WRONLY|O_NONBLOCK))==-1);//只写打开管道1,不断尝试直到成功
      for(;i<=100;i++)
      {
        sprintf(buf,"%d",rand()%3);//随机产生0-2的数字写入管道
        while(write(fp,buf,SIZE)==-1);//不断尝试写直至成功
      }
      close(fp);
      return 0; 
     } 
    /*********************************/
     pid_t p2=fork(); //产生子进程p2,程序结构同p1
    /*********************************/
     if(p2==0) 
     { 
      srand(time(NULL)+100);
      while((fp=open(FIFO2,O_WRONLY|O_NONBLOCK))==-1);
      for(;i<=100;i++)
      {
        sprintf(buf,"%d",rand()%3);
        while(write(fp,buf,SIZE)==-1);
      }
      close(fp);
      exit(0);
     }
    
    /**************************************/
    //创建2个管道
    if((mkfifo(FIFO1,0777)<0)&&(errno!=EEXIST))
    {
       printf("cannot create fifo.
    ");
       exit(1);
    }
    if((mkfifo(FIFO2,0777)<0)&&(errno!=EEXIST))
    {
       printf("cannot create fifo.
    ");
       exit(2);
    }
    
    memset(buf,0,sizeof(buf));//清空缓冲区
    //只读方式打开两个命名管道
    while((fp1=open(FIFO1,O_RDONLY|O_NONBLOCK,0))==-1);
    while((fp2=open(FIFO2,O_RDONLY|O_NONBLOCK,0))==-1);
    
    sleep(3);//等待两个子进程中打开管道写端并输入数据,必要
    for(;i<=100;i++)//连续读取100个数据
    {
      nread=read(fp1,buf,SIZE);
      if(nread!=-1&&nread!=0)
      {
       c1[i]=buf[0];//结果存放至c1
      }
    }
    i=1;
    for(;i<=100;i++)
    {
      nread=read(fp2,buf,SIZE);
      if(nread!=-1&&nread!=0)
      {
       c2[i]=buf[0];//结果存放至c2
      }
    }
    
    
    int j=1;
    int p1w=0,p2w=0,pd=0;
    for(;j<=100;j++)
    {
     int tmp=judge(c1[j],c2[j]);
     printf("round %d:",j);
     if(tmp==0)
     {
      printf("in a draw!
    ");
      pd++;//平局
     }
     else
     {
      printf("%s wins!
    ",(tmp>0)?"p1":"p2");
      if(tmp>0)p1w++;//p1胜
      else p2w++;    //p2胜
     }
    }
    //打印最终统计结果
    printf("In summary:
    ");
    printf("p1 wins %d  rounds.
    ",p1w);
    printf("p2 wins %d  rounds.
    ",p2w);
    printf("%d rounds end in a draw.
    ",pd);
    printf("%s wins in the game!
    ",(p1w>p2w)?"p1":"p2");
    
    //等待两个子进程结束
     if(waitpid(p1,&status,0) < 0)
     {
        perror("waitpid");
        exit(5);
     }
     if(waitpid(p2,&status,0)< 0)
     {
        perror("waitpid");
        exit(6);
     }
     exit(0);
    }
    
    //0——石头,1——剪刀,2——布
    int judge(char a,char b)//规定游戏判定规则
    {
     int r=0;
     if(a==b)
     r=0;
     else
     {
       if(a=='0'&&b=='1')r=1;
       if(a=='0'&&b=='2')r=-1;
       if(a=='1'&&b=='2')r=1;
       if(a=='1'&&b=='0')r=-1;
       if(a=='2'&&b=='0')r=1;
       if(a=='2'&&b=='1')r=-1;
     }
     return r;
    }
    
    
    
    

    结果:

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    [leetcode]算法题目
    JQuery功能查询页
    [C语言]一个很实用的服务端和客户端进行TCP通信的实例
    Siege——多线程编程最佳实例
    CodeIgniter框架中关于URL(index.php)的那些事
    web压测工具http_load原理分析
    【JAVA】文件各行打乱
    【JAVA】HashMap的原理及多线程下死循环的原因
    【JAVA】高并发优化细节点
    【Linux】日志分析工具grep sed sort
  • 原文地址:https://www.cnblogs.com/luo-peng/p/4646266.html
Copyright © 2020-2023  润新知