消息队列提供了一个进程向另一个进程发送数据块的方法,每个数据块都被认为是有一个类型的,这个类型下文中是用常量is_client_snd和is_server_snd来表示的
消息队列相比管道来说的优点是避免了阻塞。
系统调用函数:
#include<sys/types.h>
#include<sys/ipc.h>
原型:key_t ftok(const char* pathname,int proj_id);
参数:pathname为一个已存在的、可获得信息的文件的全路径(必须是已经存在的文件)
proj_id为任意低8位不为0的数(因为要取它的低8位)
ftok算法
返回值:成功返回一个key值 失败返回-1
2.#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
原型:int msgget(key_t key,int msgflg);
参数:key可由ftok获得
flag可取三个值 IPC_CREAT IPC_EXCL IPC_CREAT|IPC_EXCL
IPC_CREAT 创建一个消息队列并返回队列的标识,如果该队列已存在则直接返回该标识
IPC_EXCL 本身并没多大意思,通常和IPC_CREAT一起使用
IPC_CREAT|IPC_EXCL 创建消息队列,如果该队列已经存在则直接返回-1报错,保证资源是 新建的而不是打开的
返回值:成功返回队列标识 _msg_id 失败返回-1
3.#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
接收消息:ssize_t msgrcv(int msgid, const void *msgp,size_t msgsz,int msgtyp,int msgflg);
发送消息:int msgsnd(int msgid,const void *msgp,size_t msgsz,int msgflg));
参 数: msg_id为消息队列的标识, msgp为指向消息缓冲区的指针(用户可自己制定的通用结构)
msgsz为消息的大小,msftyp为从队列中取消息的类型,为0可以取任何消息,
msgflg指明当消息队列中没消息时应该做的指示,0为阻塞,IPC_NOWAIT则直接返回-1;
用到的命令:
ipcs -q //查看系统中存在的消息队列
ipcrm -q key值 //删除指定的key值的消息队列
//comm.h
#ifndef _MSG_QUEUE_
#define _MSG_QUEUE_
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<stdlib.h>
#include<sys/msg.h>
#include<string.h>
#define _PATH_ "/tmp/.msg"
#define _PROJ_ID_ 0x55
#define _MSG_SIZE_ 1024
extern const long is_server_snd;
extern const long is_client_snd;
typedef struct _msg_info _msg_info;
struct _msg_info
{
int mtype;
char mtext[_MSG_SIZE_];
};
static int comm_msg(int flag);
int creat_msg_queue();
int get_msg_queue();
int destroy(int msg_id);
#endif
//comm.c
#include"comm.h"
const long is_server_snd=1;
const long is_client_snd=2;
static int comm_msg(int flag)
{
key_t _key=ftok(_PATH_,_PROJ_ID_);
if(_key<0){
perror("ftok");
return -1;
}
int msg_id= msgget(_key,flag);
if(msg_id<0){
perror("msgget");
return -1;
}
else
return msg_id;
}
int creat_msg_queue()
{
return comm_msg(IPC_CREAT|IPC_EXCL);
}
int get_msg_queue()
{
return comm_msg(IPC_CREAT);
}
int destroy(int msg_id)
{
return msgctl(msg_id,IPC_RMID,NULL);
}
//server.c
#include"comm.h"
int main()
{
int _msg_id=creat_msg_queue();
_msg_info msginfo;
while(1){
msginfo.mtype=is_client_snd;
memset(msginfo.mtext,'\0',sizeof(msginfo.mtext));
if(msgrcv(_msg_id,&msginfo,sizeof(msginfo.mtext),is_client_snd,0)<0){
perror("msgrcv");
}
else{
printf("client say# %s",msginfo.mtext);
}
msginfo.mtype=is_server_snd;
memset(msginfo.mtext,'\0',sizeof(msginfo.mtext));
read(0,msginfo.mtext,sizeof(msginfo.mtext));
if(msgsnd(_msg_id,&msginfo,sizeof(msginfo),0)<0){
perror("msgsnd");
}
}
if(destory(_msg_id)!=0){
perror("destory failed!\n");
}
else
printf("destory success!\n");
return 0;
}
//client.c
#include"comm.h"
int main()
{
int _msg_id= get_msg_queue();
_msg_info msginfo;
while(1){
memset(msginfo.mtext,'\0',sizeof(msginfo.mtext));
msginfo.mtype=is_client_snd;
if(read(0,msginfo.mtext,sizeof(msginfo.mtext))>=0){
if(msgsnd(_msg_id,&msginfo,sizeof(msginfo.mtext),0)<0){
perror("msgsnd");
}
}
memset(msginfo.mtext,'\0',sizeof(msginfo.mtext));
if(msgrcv(_msg_id,&msginfo,sizeof(msginfo),is_server_snd,0)<0){
perror("msgrcv");
}
else{
printf("server say# %s",msginfo.mtext);
}
}
return 0;
}
//Makefile
.PHONY:all
all:server client
server:server.c comm.c
gcc -o server server.c comm.c
client:client.c comm.c
gcc -o client client.c comm.c
.PHONY:clean
clean:
rm -rf server client
转载于:https://blog.51cto.com/lingdandan/1763140