1.消息队列什么?
首先我们在学习数据结构后应该对队列有了一个确切的理解,那么在Linux下进程间通信(System V进程间通信)就有这么一种机制。**消息队列概念:**也叫报文队列,其实就是一个消息的链表,发送的数据就是带有类型的数据块。
2.消息队列特性:
1.消息队列是操作系统在内核为我们创建的一个队列。
2.数据传输:用户组织一个带有类型的数据块,添加到队列中,其他进程从队列中读取特定类型的数据。
3.消息队列是全双工(可读可写)。关于全双工对照着半双工去理解即可。
4.消息队列的生命周期随内核。
3.消息队列的操作步骤:
1.创建/打开消息队列。
2.发送数据/接收数据
3.释放消息队列。
4.消息队列各步骤函数原型:
- 创建/或打开消息队列:
int msgget(key_t key, int msgflg);
参数:
key:内核中消息队列的标识。
msgflg:IPC_CREAT 不存在时创建消息队列,存在时则打开。
IPC_EXCL与IPC_CREAT同用时,若存在则报错。
mode权限。
返回值:成功时返回消息队列句柄;失败时返回-1;
**注意:**key可以通过函数ftok生成
ftok函数原型:
key_t ftok(const char *pathname, int proj_id);
ftok通过文件的inode节点号与proj_id计算得到一个key值。不过这样会存在一个缺点:当这个文件被删除或丢失的时候,这个消息队列再通过这样的方式就有可能找不到了。
- 发送消息:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:
msqid:操作句柄msgget返回值。
msgp:结构体masgbuf,用户自定义,描述msg类型、以及msg正文。
msgsz:发送数据的大小即就是sizeof(mtext)大小。
msgflg:标志选项。
返回值:成功返回发送的实际字节数,失败返回:-1。
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
- 接收消息:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
参数:
msqid:操作句柄msgget返回值。
msgp:结构体masgbuf,用户自定义,描述msg类型、以及msg正文。
msgsz:期望接收数据的大小。
msgflg:标志选项。0表示如果接收的数据大于msgsz时,接收数据自动截断,否则不截断。
返回值:成功返回发送的实际字节数,失败返回:-1。
- 消息队列的释放:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数:
msqid:消息队列操作句柄。
cmd:操作选项,常用IPC_RMID,用于删除消息队列。
buf:用于保存消息队列的信息,不需要则可以忽略(NULL)。
返回值:成功0,失败返回-1。
了解这些接口及使用方法就可以直接上代码了
还是server&client通信
server.c:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#define KEY 0x123456
#define C 1
#define S 2
//存储消息的结构体
struct msgbuf
{
long mtype;
char mtext[1024];
};
int main()
{
//1.打开/创建消息队列
int msgid = msgget(KEY,IPC_CREAT|0664);
struct msgbuf buf;
while(1)
{
printf("please wait the client request...\n");
//server端接收数据
msgrcv(msgid,&buf,1024,C,0);
printf("client say:");
fflush(stdout);
printf("%s\n",buf.mtext);
printf("server enter#:");
fflush(stdout);
scanf("%s",&buf.mtext);
//server端发送数据
buf.mtype = S;
msgsnd(msgid,&buf,strlen(buf.mtext),0);
}
//server端删除消息队列
msgctl(msgid,IPC_RMID,NULL);
return 0;
}
client.c:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>
#define KEY 0x123456
#define C 1
#define S 2
//存储消息的结构体
struct msgbuf
{
long mtype;
char mtext[1024];
};
int main()
{
//1.打开消息队列
int msgid = msgget(KEY,IPC_CREAT|0664);
struct msgbuf buf;
while(1)
{
printf("client enter#:");
fflush(stdout);
scanf("%s",&buf.mtext);
//client发送消息
buf.mtype = C;
msgsnd(msgid,&buf,strlen(buf.mtext),0);
printf("please the server respond...\n");
msgrcv(msgid,&buf,1024,S,0);
printf("server say:");
fflush(stdout);
printf("%s\n",buf.mtext);
}
return 0;
}
运行效果展示:
server端:
client端: