LINUX使用消息机制的示例程序

使用消息机制的示例程序

http://blog.sina.com.cn/s/blog_6334fe7c0100fvtl.html

示例程序执行的进程分为两种,分别称为服务进程和客户进程:服务进程只有一个,接收各客户进程以消息形式发出的问题,接收键盘输入作为回答,再以消息形式送给提问的进程。各客户进程接收键盘输入作为问题,以消息形式发给服务进程,等待接收服务进程发来的回答消息,再开始下一轮的循环。示例程序的实际执行效果如下:

      编译后执行,第一个进程实例将作为服务进程,提示:

             ACT SERVER!!! Wait question and give answer.

       To end this process, try Ctrl+C or use kill.

      服务进程一直循环执行,直到用户按Ctrl+C终止执行,或使用kill命令杀死服务进程。

      其他进程实例作为客户进程,提示:

             Act as client, ask question and wait answer!

       To end this process, enter end as input question.

      客户进程一直循环执行,直到用户输入end。

示例程序的代码如下:

#include <sys/types.h>

#include <unistd.h>

#include <signal.h>

#include <stdio.h>

#include <string.h>

#include <sys/ipc.h>

#include <sys/msg.h>

 

#define MY_KEY10071140          // need to change

#define SERVER_ID 2

#define MAX_BUF 200

 

void sigend(int);

 

struct mymsg {

    longmtype;

    longpid;

    charbuf[MAX_BUF];

};

 

int msgid;

int main(void)

{

    structmymsg msgbuf;//定义一结构变量

       //建立一个共享存储区;

   if((msgid=msgget(MY_KEY, IPC_CREAT|IPC_EXCL|0666)) <0 )

              

     

       msgid=msgget(MY_KEY, 0666);

 

       printf("Act as client, ask question and wait answer!\n");

       printf("To end this process, enter end as inputquestion.\n\n");

 

              //I/O中断

       printf("Input question in one line:\n");

       fgets(msgbuf.buf, sizeof(struct mymsg)-2*sizeof(long)-1,stdin);

 

       while(strcmp(msgbuf.buf,"end\n"))

       {

                     //获得服务进程号

           msgbuf.mtype=SERVER_ID;

 

                     //获得当前进程的进程号

           msgbuf.pid=getpid();

 

                     //发送消息;

           msgsnd(msgid,&msgbuf, sizeof(struct mymsg)-sizeof(long), 0);

           

                        //接收消息;

msgrcv(msgid, &msgbuf, sizeof(struct mymsg),getpid(), 0);

 

           printf("Answer from server: \n%s", msgbuf.buf);

           printf("Input question in one line:\n");

           fgets(msgbuf.buf, sizeof(struct mymsg)-2*sizeof(long)-1,stdin);

       }

    }

   else         

    {

       signal(SIGINT, sigend);

       signal(SIGTERM, sigend);

       printf("ACT SERVER!!! Wait question and give answer.\n");

       printf("To end this process, try Ctrl+C or use kill.\n\n");

      

       while(1)

       {

                     //接收消息;

           msgrcv(msgid, &msgbuf, sizeof(struct mymsg),SERVER_ID, 0);

           printf("Question from %d: \n%sGive answer:\n", (int)msgbuf.pid,msgbuf.buf);

           fgets(msgbuf.buf, sizeof(struct mymsg)-2*sizeof(long)-1,stdin);

                     

           msgbuf.mtype=msgbuf.pid;

 

                     //发送消息;

           msgsnd(msgid, &msgbuf, sizeof(structmymsg)-sizeof(long), 0);

       }

    }

}

 

void sigend(int sig)

{

             //操纵一个消息队列;

   msgctl(msgid, IPC_RMID, 0);

   exit(0);

}

1》运行注意:运行前先在#define MY_KEY 10071140 修改MY_KEY的值

2》运行步骤:

打开一个终端,  gccst.c        ./a.out

输出:

ACT SERVER!! Wait question and give answer.

To end this process,try Ctrl+C or use kill.

   即:为服务进程

3》然后再打开一个终端,键入 ./a.out,输出

Act as slient,ask question and wait answer!

To end this process,enter end as input question.

可知,该终端执行的进程是客户进程。

4》再客户进程输入要提问的问题,然后服务进程可以看到客户的输入,

并可以再服务进程输入问题的答案,客户进程也可以看到。

通过键入“end”可以结束客户进程,键入Ctrl+C或kill可以结束服务进程。

      

      具体输出如下:

客户进程                       服务进程

Act asslient,…..                 ACT SERVER!! ………

 

To end thisprocess…….           To end thisprocess…….            

 

Input question in oneline:       

aaa                            Question from 12625:

                               aaa

                               Give answer:

                               aaaaaaa

Answer from server:

aaaaaaa

Input question in one line:

………………..                  …………

Input question in one line:

end

(客户进程结束)               Ctrl+C

                               (服务进程结束)

 

5》从而通过msgsnd()发送消息和msgrcv()接收消息实现的消息机制实现了进程间通信

 

修改部分的描述,执行结果的描述和分析;

  改后代码:

//=========== st1.cpp======== 独立服务客户端  ==========

 

#include<sys/types.h>

#include<unistd.h>

#include<signal.h>

#include<stdio.h>

#include<string.h>

#include<sys/ipc.h>

#include<sys/msg.h>

 

#define MY_KEY12345678    // need to change,必须与服务端一致

#define SERVER_ID 2

#define MAX_BUF 200

 

void sigend(int);

 

struct mymsg {

    longmtype;

    longpid;

    charbuf[MAX_BUF];

};

 

int msgid;

int main(void)

{

    //message iscreated sucessfully, the first SERVER ran !

   if((msgid=msgget(MY_KEY, IPC_CREAT|IPC_EXCL|0666)) <0 )

        

       printf("SERVER ran again, Error\n!");

       exit(0);

    }

   else       

    {

       struct mymsg msgbuf;//定义一结构变量

       signal(SIGINT, sigend);

       signal(SIGTERM, sigend);

       printf("ACT SERVER!!! Wait question and give answer.\n");

       printf("To end this process, try Ctrl+C or use kill.\n\n");

       while(1)

       {

           //接收消息;

           msgrcv(msgid, &msgbuf, sizeof(struct mymsg),SERVER_ID, 0);

           printf("Question from %d: \n%sGive answer:\n", (int)msgbuf.pid,msgbuf.buf);

           fgets(msgbuf.buf, sizeof(struct mymsg)-2*sizeof(long)-1,stdin);

               

           msgbuf.mtype=msgbuf.pid;

 

               //发送消息;

           msgsnd(msgid, &msgbuf, sizeof(structmymsg)-sizeof(long), 0);

       }

    }

    return0;

}

 

void sigend(int sig)

{

   msgctl(msgid, IPC_RMID, 0);//操纵一个消息队列;

    exit(0);

}

 

//=========== st2.cpp======== 独立实现客户端  ==========

 

#include<sys/types.h>

#include<unistd.h>

#include<signal.h>

#include<stdio.h>

#include<string.h>

#include<sys/ipc.h>

#include<sys/msg.h>

 

#define MY_KEY10071140    // need to change

#define SERVER_ID 2

#define MAX_BUF 200

 

void sigend(int);

 

struct mymsg {

    longmtype;

    longpid;

    charbuf[MAX_BUF];

};

 

int msgid;

int main(void)

{

   if((msgid=msgget(MY_KEY, IPC_CREAT|IPC_EXCL|0666)) <0 )

    {

       struct mymsg msgbuf;//定义一结构变量

       msgid=msgget(MY_KEY, 0666);

       printf("Act as client, ask question and wait answer!\n");

       printf("To end this process, enter end as inputquestion.\n\n");

           //I/O中断

       printf("Input question in one line:\n");

       fgets(msgbuf.buf, sizeof(struct mymsg)-2*sizeof(long)-1,stdin);

       while(strcmp(msgbuf.buf,"end\n"))

        

           msgbuf.mtype=SERVER_ID;//获得服务进程号

           msgbuf.pid=getpid();//获得当前进程的进程号 

           msgsnd(msgid, &msgbuf, sizeof(structmymsg)-sizeof(long), 0);//发送消息;

           msgrcv(msgid, &msgbuf, sizeof(struct mymsg),getpid(), 0);//接收消息;

           printf("Answer from server: \n%s", msgbuf.buf);

           printf("Input question in one line:\n");

           fgets(msgbuf.buf, sizeof(struct mymsg)-2*sizeof(long)-1,stdin);

       }

    }

    else

    {

       printf("SEVER must ran firstly,Error!\n");

       exit(0);

    }

}

void sigend(int sig)

{

       //操纵一个消息队列;

   msgctl(msgid, IPC_RMID, 0);

    exit(0);

}

执行结果描述及分析:

1》运行注意:运行前先在#define MY_KEY 10071140 修改MY_KEY的值

2》运行步骤:

打开一个终端,  makest1      ./st1

输出:

ACT SERVER!! Wait question and give answer.

To end this process,try Ctrl+C or use kill.

   即:为服务进程

3》然后再打开一个终端,键入makest1      ./st1

输出

Act as slient,ask question and wait answer!

To end this process,enter end as input question.

可知,该终端执行的进程是客户进程。

4》再客户进程输入要提问的问题,然后服务进程可以看到客户的输入,

并可以再服务进程输入问题的答案,客户进程也可以看到。

通过键入“end”可以结束客户进程,键入Ctrl+C或kill可以结束服务进程。

      

      具体输出如下:

客户进程                       服务进程

Act asslient,…..                 ACT SERVER!! ………

 

To end thisprocess…….           To end thisprocess…….            

 

Input question in oneline:       

aaa                            Questionfrom 12625:

                               aaa

                               Give answer:

                               aaaaaaa

Answer from server:

aaaaaaa

Input question in one line:

………………..                  …………

Input question in one line:

end

(客户进程结束)               Ctrl+C

                               (服务进程结束)

 

5》从而通过msgsnd()发送消息和msgrcv()接收消息实现的消息机制实现了进程间通信。

分析:

1》用MK-KEY作参数创建消息队列,因一个MK-KEY只能创建一个消息队列,故在st1.c中通过判断创建信息队列是否成功,来实现唯一创建服务进程的目的。

2》st2.c和st1.c即客户进程要与服务进程的MK-KEY的值相同,才能保证二者通过在服务进程创建的消息队列进行信息交互。 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值