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的值相同,才能保证二者通过在服务进程创建的消息队列进行信息交互。
相关文章推荐
- OSAL消息机制及使用示例
- Linux下,使用C/C++一个简单的消息处理程序
- 【Linux C代码分享二】UDP Socket示例程序:使用fgets函数获取屏幕输入
- 微信小程序开发之formId使用(模板消息)、跨页面获取数据示例
- 使用socket的Linux上的C语言文件传输顺序服务器和客户端示例程序
- 使用socket的Linux上的C语言文件传输顺序服务器和客户端示例程序
- 使用socket的Linux上的C语言文件传输顺序服务器和客户端示例程序
- 使用socket的Linux上的C语言文件传输顺序服务器和客户端示例程序
- 使用socket的Linux上的C语言文件传输顺序服务器和客户端示例程序
- 使用消息分发机制降低程序中的耦合度
- QT5使用消息机制及程序发布相关
- Linux下进程之间通过消息队列通信小程序示例
- 使用socket的Linux上的C语言文件传输顺序服务器和客户端示例程序
- linux c/c++ 聊天小程序代码示例 (使用socket 和 IO 多路复用技术)
- Eclipse中使用Hadoop伪分布模式开发配置及简单程序示例(Linux下)
- Linux下,使用C/C++编写一个简单的消息处理程序
- Linux - 使用gdb调试多进程程序
- 编写一段程序,从标准输入读取string对象的序列直到连续出现两个相同的单词或者所有单词都读完为止。使用while循环一次读取一个单词,当一个单词连续出现两次是使用break语句终止循环。输出连续重复出现的单词,或者输出一个消息说明没有人任何单词是重复出现的。
- JAVA程序退出时执行的操作Runtime类的addShutdownHook函数使用示例
- Linux进程间通信——使用消息队列