您的位置:首页 > 运维架构 > Linux

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

2011-12-14 09:07 357 查看

使用消息机制的示例程序

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的值相同,才能保证二者通过在服务进程创建的消息队列进行信息交互。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐