消息隊列:一個進程向另一個進程發送數據塊
消息隊列基於消息,管道基於字節流
消息隊列是用鏈表實現
1.創建:int megget(key_t key, int msgflag)
key:函數ftok()的返回值
msgflag:IPC_CREAT是創建新的消息隊列;IPC_EXCL與IPC_CREAT一起使用,即如果要創建的消息隊列已存在,則返回錯誤
成功:返回隊列標識符
失敗:-1
2.獲取:ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
msqid:消息隊列的識別碼
msgp:指向消息緩沖區的指針,用來暫時存儲發送和接收的消息,是用戶自己定義的一個通用結構
struct msgbuf
{
long mtype; //消息類型,必須> 0
char mtext[__SIZE__]; //消息文本
}
msgsz:消息大小
msgtyp:消息類型(>0,返回其類型為mtype的第一個消息)
msgflg:控制函數行為(0表示忽略)
成功:返回拷貝到mtext數組的實際字節數
失敗:-1
3.發送:int msgsnd(int msqid, void *msgp, size_t msgsz, int msgflg)
成功:返回0
失敗:-1
4.設置屬性:int msgctl(int msqid, int cmd, struct msqid_ds *buf)
對msqid標識的消息隊列執行cmd操作
cmd操作:IPC_STAT(獲取對應的msqid_ds的數據結構,保存在buf指定的地址空間)
IPC_SET(設置消息隊列的屬性,保存在buf中)
IPC_RMID(從內核刪除msqid標識的消息隊列)
msqid_ds:描述隊列當前狀態
成功:0
失敗:-1
comm.h
#ifndef __COMM__
#define __COMM__
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <string.h>
#define __SIZE__ 1024
#define FILEPATH "/tmp/.msg1"
#define ID 0
const int ser_send_type=1;
const int cli_send_type=2;
typedef struct msg_info
{
char mtext[__SIZE__];
long mtype;
}msginfo;
#endif
client.h
#ifndef __CLIENT__
#define __CLIENT__
#include "comm.h"
int cli_start();
int cli_end(int);
#endif
client.c
#include "client.h"
int msg_id= -1;
int cli_start()
{
//create the client's buf which storage the msg
msginfo cli_info;
//create the key
key_t key= ftok(FILEPATH, ID);
if(key< 0)
{
perror("ftok");
exit(1);
}
//get the ID of msg_queue
msg_id= msgget(key, 0);
if(msg_id< 0)
{
perror("cli get key id failed");
exit(2);
}
while(1)
{
//client said
printf("client:>");
fgets(cli_info.mtext, __SIZE__, stdin); //write in the cli_info
//when it will exit?
if(strncasecmp(cli_info.mtext, "quit", 4)==0)
{
printf("client bye!\n");
break;
}
cli_info.mtype= cli_send_type;
//send the msg(send judge)
if(msgsnd(msg_id, &cli_info, sizeof(cli_info.mtext),0)== -1) //send fail
{
perror("client send msg fail");
exit(3);
}
//receive the msg
memset(cli_info.mtext, '\0', sizeof(cli_info.mtext)); //reset first
if(msgrcv(msg_id, &cli_info, sizeof(cli_info.mtext), ser_send_type, 0)==-1) //receive fail
{
perror("client msgrcv fail");
exit(4);
}
printf("server:>%s\n", cli_info.mtext); //the msg receive from server have storaged in the cli_info.mtext
fflush(stdout);
}
return 0;
}
int cli_end(int id)
{
if(msgctl(id, IPC_RMID, NULL)==-1) //fail
{
perror("delete th msg_queue from kernel fail");
exit(5);
}
else
{
printf("delete the msg_queue from kernel success\n");
return 0;
}
}
static void delete_msg(void)
{
if(msg_id!= -1) //the msg_queue exist
{
cli_end(msg_id);
}
printf("delete the msg queue end\n");
}
int main(int argc,char *argv[])
{
atexit(delete_msg);
if(cli_start()==0)
{
printf("cli start success\n");
}
else
{
printf("cli start failed\n");
}
return 0;
}
server.h
#ifndef __SERVER__
#define __SERVER__
#include "comm.h"
int ser_start();
int ser_end(int);
#endif
server.c
#include "server.h"
int msg_id= -1;
int ser_start()
{
//create the server's buf which storage the msg
msginfo ser_info;
//create the key
key_t key= ftok(FILEPATH, ID);
if(key< 0)
{
perror("ftok");
exit(1);
}
//get the ID of msg_queue
msg_id= msgget(key, IPC_CREAT|IPC_CREAT|0666);
if(msg_id< 0)
{
perror("ser get key id failed");
exit(2);
}
while(1)
{
//reveive the msg
if(msgrcv(msg_id, &ser_info, sizeof(ser_info.mtext), cli_send_type, 0)==-1) //fail
{
perror("server msgrcv fail");
exit(3);
}
printf("client:>%s\n",ser_info.mtext); //first,output the client's msg
printf("server:>"); //then,server will said
memset(ser_info.mtext, '\0', sizeof(ser_info.mtext)); //reset first
fgets(ser_info.mtext, __SIZE__, stdin); //write in the ser_info
//when it will exit?
if(strncasecmp(ser_info.mtext, "quit", 4)==0)
{
printf("server bye!\n");
break;
}
ser_info.mtype= ser_send_type;
//send the msg
if(msgsnd(msg_id, &ser_info, __SIZE__, 0)==-1) //fail
{
perror("server msgsnd fail");
exit(4);
}
fflush(stdout);
}
return 0;
}
int ser_end(int id)
{
if(msgctl(id, IPC_RMID, NULL)== -1) //fail
{
perror("delete the msg_queue from kernel fail");
exit(5);
}
else
{
printf("delete the msg_queue from kernel success\n ");
return 0;
}
}
static void delete_msg(void)
{
if(msg_id!= -1) //the msg_queue exist
{
ser_end(msg_id);
}
printf("delete the msg_queue end\n");
}
int main(int argc, char *argv[])
{
atexit(delete_msg);
if(ser_start()==0) //success
{
printf("ser start success\n");
}
else
{
printf("ser start failed\n");
}
return 0;
}
Makefile
.PHONY:all
all:client server
client:client.c
gcc -o $@ $^
server:server.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f client server