实验目的
1、了解什么是消息、消息队列
2、掌握消息传送的机理
msgget
作用:创建消息队列
原型:int msgget(key_t key, int msgflag)
参数:key:键值 IPC_PRIVATE
msgflag:权限
返回值:成功:消息队列ID
出错:-1
头文件: #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
错误:
msgsnd
作用:写数据到消息队列
原型:int msgsnd(int msgid, const void *msggp, size_t msgsize, int msgflg)
参数:msgid消息队列标识符
msggp 消息结构
例如下:
struct msgtype
{
long mtype; /消息类型/
char mtext[256]; /消息正文/
}
msgsize,字节数
msgflg,标识符分类如下
0:当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列
IPC_NOWAIT:当消息队列已满的时候,msgsnd函数不等待立即返回
IPC_NOERROR:若发送的消息大于size字节,则把该消息截断,截断部分将被丢弃,且不通知发送进程。
头文件: #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
错误:
msgrcv
作用:从消息队列中读数据
原型:ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, intmsgflg)
参数:msqid:消息队列标识符
msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如上方的msggp
msgsz:消息的大小。
msgtyp:消息类型
msgtyp等于0 则返回队列的最早的一个消息
msgtyp大于0,则返回其类型为mtype的第一个消息
msgtyp小于0,则返回其类型小于或等于mtype参数的绝对值的最小的一个消息
错误:
msgctl
作用:控制消息队列
原型:int msggctl(intmsgid, int cmd, struct msgid_ds *buf)
参数:msgid 消息队列ID
cmd 命令参数
IPC_STAT 读取消息队列的数据结构, IPC_SET设置消息队列数据结构msgid_ds中的IPC操作权限、 IPC_RMID从系统内核汇总删除消息队列
返回值: 成功 0
出错-1
头文件: #include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
错误:
所作实验代码
要求
将server程序设置为能够并发处理多个客户的程序(参考下图的程序结构),服务器无限循环,CTRL+C结束,设计捕捉信号,信号处理中删除消息队列,服务器收到客户机的消息后发给不同客户机不同的应答消息(内容自定)。
server
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdio.h>
#include <unistd.h>
#include<stdlib.h>
#include <string.h>
#include<signal.h>
#define MSGKEY 75
struct msgform
{
long mtype;
char mtext[256];
};
int msgid;
void stop(int a){
printf("server will stop in one second\n");
sleep(1);
msgctl(msgid,IPC_RMID,0);
exit(0);
}
int main()
{
int pid;
if( (pid = fork()) == -1){
perror("fork");
exit(EXIT_FAILURE);
}
else if ( pid == 0) //子进程
{
struct msgform msg1,msg2;
msgid=msgget(MSGKEY,0777|IPC_CREAT); /*创建消息队列,操作权为可读、写、执行*/
while(1){
sleep(2);
msgrcv(msgid,(void *) &msg1,256,1,0); /*接收flag==1消息*/
printf("server receive client 1:%s",msg1.mtext);
strcpy(msg2.mtext,"server received!");
msg2.mtype=1;
msgsnd(msgid,&msg2,256,0); /*发送消息*/
}
}
else //父进程
{
if((pid=fork())==-1){
perror("fork");
exit(0);
}
else if(pid==0){//second child
struct msgform msg1,msg2;
msgid=msgget(MSGKEY,0777|IPC_CREAT); /*创建消息队列,操作权为可读、写、执行*/
while(1){
sleep(2);
msgrcv(msgid,(void *) &msg1,256,2,0); /*接收flag==2消息*/
printf("server receive client 2:%s",msg1.mtext);
strcpy(msg2.mtext,"server received!");
msg2.mtype=2;
msgsnd(msgid,&msg2,256,0); /*发送消息*/
}
}
else{
printf("press ctrl+c exit!!!\n");
signal(SIGINT,stop);
while(1);
}
}
}
client
有两个client,代码一致
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#define MSGKEY 75
struct msgform
{
long mtype; /*消息类型*/
char mtext[256]; /*消息正文*/
};
int msgid;
int main()
{
char buffer[256];
struct msgform msg1,msg2;
int msgid,pid,*pint;
msgid=msgget(MSGKEY, 0777); /*打开消息队列*/
printf("Enter the mssage to send:");
fgets(msg1.mtext,156,stdin);
msg1.mtype = 1;
msgsnd(msgid,&msg1,256,0); /*发送消息*/
msgrcv(msgid,&msg2,256,1,0); /*接收类型为2的消息*/
printf("receive from server: %s\n",msg2.mtext);
}
运行结果