利用消息队列针对发送接受消息的类型唯一性 进行多个客户端之间消息传递,而不需要server端进行消息转发。
同时消息队列的读阻塞和写阻塞特性(消息队列中已经写入数据,如果再不读出来,则无法再次写入)让消息队列的实现过程只能如下:
客户端1 client1.c
#include
#include
#include
#include
#include
#include
#include
#define MSG_TYPE1 1
#define MSG_TYPE2 2
struct msgbuf
{
long mtype;
char mtext[100];
};
int main()
{
//当多用户的时候通过指定文件以及设置id来获取唯一的key标识
//key_t key = ftok(".",100);
key_t key = 12345; //个人使用的时候可以直接指定key
//创建msg_qid的对象
int msg_qid = msgget(key, IPC_CREAT | 0666);
struct msgbuf msg1,msg2;
int ret;
char send_buf[100],rcv_buf[100];
ret = fork();
if ( -1 == ret ) {
printf("fork failed! \n");
_exit(-1);
}
//子进程处理消息1的写
else if (ret == 0) {
while(1) {
memset(&msg1, 0 , sizeof(msg1));
//初始化消息类型以及消息内容
scanf("%s",msg1.mtext);
msg1.mtype = MSG_TYPE1;
//发送消息到消息标识的msg_qid IPC 对象中
/* if( -1 == msgsnd(msg_qid,(void *)&msg1,strlen(msg1.mtext),0)) {
printf("send msg1 failed\n");
_exit(-1);
}*/
msgsnd(msg_qid,(void *)&msg1,strlen(msg1.mtext),0);
}
}
//父进程处理消息2的读
else {
while(1) {
memset(&msg2, 0, sizeof(msg2));
//获取消息大小为sizeof(msg2.mtext)
if (-1 == msgrcv(msg_qid,(void*)&msg2,sizeof(msg2.mtext),MSG_TYPE2,0)){
printf("receive msg2 failed\n");
_exit(-1);
}
printf("client1:%s\n",msg2.mtext);
}
}
msgctl(msg_qid,IPC_RMID,NULL);
return 0;
}
客户端2 client2.c
#include
#include
#include
#include
#include
#include
#include
#define MSG_TYPE1 1
#define MSG_TYPE2 2
struct msgbuf
{
long mtype;
char mtext[100];
};
int main()
{
//当多用户的时候通过指定文件以及设置id来获取唯一的key标识
//key_t key = ftok(".",100);
key_t key = 12345; //个人使用的时候可以直接指定key
//创建msg_qid的对象
int msg_qid = msgget(key, IPC_CREAT | 0666);
struct msgbuf msg1,msg2;
int ret;
ret = fork();
if ( -1 == ret ) {
printf("fork failed! \n");
_exit(-1);
}
else if (ret == 0) {
while(1) {
memset(&msg1, 0 , sizeof(msg1));
//初始化消息类型以及消息内容
scanf("%s",msg1.mtext);
msg1.mtype = MSG_TYPE2;
//发送消息到消息标识的msg_qid IPC 对象中
/*if( -1 == msgsnd(msg_qid,(void *)&msg1,strlen(msg1.mtext),0)) {
printf("send msg1 failed\n");
_exit(-1);
}*/
msgsnd(msg_qid,&msg1,100,0);
}
}
else {
while(1) {
memset(&msg2, 0, sizeof(msg2));
if (-1 == msgrcv(msg_qid,(void*)&msg2,sizeof(msg2.mtext),MSG_TYPE1,0)){
printf("receive msg2 failed\n");
_exit(-1);
}
printf("client2:%s\n",msg2.mtext);
}
}
msgctl(msg_qid,IPC_RMID,NULL);
return 0;
}
消息队列相关命令
ipcs -q
查看系统消息队列
ipcrm -q msqid
按照消息标识删除当前用户下的消息队列
ipcmk -Q
创建消息队列
差异:
共同点:
消息的接受和发送都是阻塞读和阻塞写,即需要将写的内容读出,否则下次发送会阻塞写