What is a message queue?
Message queues provide a way to send a typed block of data from one process to another. In this way, synchronization and blocking of named pipes can be avoided. Message queues are message-based, while pipelines are byte stream-based, and message queues are not necessarily read first in first out.
Operation of message queue:
Creation or acquisition of message queues:
int msgget(key_t key, int msgflg);
Parameter description:
key: is a port number that can be generated by ftok()
msgflg: IPC_CREAT: If IPC does not exist, create it and open it.
IPC_EXECL: It doesn't make much sense to use it alone. With the use of IPC_CREAT as a representative, IPC is not created, there are errors, return
key_t ftok(const char *pathname, int proj_id);
Generate a unique key for the user to use and return a message queue identifier.
Return value:
The id of the message queue is returned successfully, and - 1 is returned unsuccessfully.
Read the message:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
Parameter description:
msgid: identifier of message queue
msgp: A pointer to a buffer that temporarily stores messages sent and received. It is a user-defined universal structure.
struct msgstru{
long mtype; //greater than 0
char mtext; //User specified size
};
msgz: message size
msgtyp: Message form read from message queues
Msgflg: Used to specify actions that the core program should take in the absence of data in the queue. If msgflg and constant IPC_NOWAIT are used together, msgsnd() will not block if the message queue is full at the time of execution of msgsnd(), but will return to - 1 immediately. If msgrcv() holds the line, return to - 1 immediately without waiting for the message queue to be empty, and set the error code as ENOMSG. When msgflg is 0, msgsnd() and msgrcv() take the blocking waiting mode when the queue is full or empty.
Return value:
Successfully returns the number of bytes actually read, and fails to return - 1.
Send a message:
int msgsnd(int msqid, const void *msgp, size_t msgz, int msgflg);
The parameters are the same as those of the read message function.
Return value;
Successful return 0, Failure Return - 1.
View the message queue:
Ipcs-q can be used to view message queues in the system.
You can use ipcrm-q+ipc id to delete message queues corresponding to IDS
Examples of message queues:
Implement a server and a client program that communicate with each other using message queues.
comm.h
#ifndef _COMM_H_ #define _COMM_H_ #ifndef _COMM_H_ #define _COMM_H_ #include<stdio.h> #include<sys/types.h> #include<sys/ipc.h> #include<sys/msg.h> #include<string.h> #define PATHNAME "." #define PROJ_ID 0x666 #define SERVER_TYPE 1 #define CLIENT_TYPE 2 //Customize a buffer to temporarily store data sent or received struct msgbuf { long mytype; char mtext[1024]; }; int createMsgQueue(); int getMsgQueue(); int destroyMsgQueue(int msgid); int sendMsg(int msgid, int type, char *msg); int recvMsg(int msgid, int recvType, char out[]); #endif
comm.c
#include "comm.h" //Create or open message queues static int commMsgQueue(int flag) { key_t key = ftok(PATHNAME, PROJ_ID); if(key < 0) { perror("ftok"); return -1; } //Open or create according to flag's different choices int msgid = msgget(key, flag); if(msgid < 0) { perror("msgget"); return -2; } return msgid; } int createMsgQueue() { return commMsgQueue(IPC_CREAT|IPC_EXCL|0666); } int getMsgQueue() { return commMsgQueue(IPC_CREAT); } int destroyMsgQueue(int msgid) { //Delete message queue if(msgctl(msgid, IPC_RMID, NULL)<0) { perror("msgctl"); return -1; } return 0; } //Send messages (parameters: sender, type of content to be sent, content to be sent) int sendMsg(int msgid, int who, char *msg) { //buf Custom Buffer for Temporary Data Storage struct msgbuf buf; buf.mytype = who; strcpy(buf.mtext, msg); //Send, send data in the buffer if(msgsnd(msgid, (void *)&buf, sizeof(buf.mtext), 0) < 0) { perror("msgsnd"); return -1; } return 0; } //Receive messages (parameters: recipient, acceptance type, storage location after acceptance) int recvMsg(int msgid, int who, char out[]) { struct msgbuf buf; buf.mytype = who; //Receive data and write the received data to the buffer if(msgrcv(msgid, (void *)&buf, sizeof(buf.mtext), recvType, 0)< 0) { perror("msgrcv"); return -1; } //Store data from buffer to specified location strcpy(out, buf.mtext); return 0; }
server.c
#include"comm.h" int main() { //Server-side message queue creation int msgid = createMsgQueue(); //Buffer char buf[1024]; while(1) { buf[0] = 0; //Accept messages sent by clients recvMsg(msgid, CLIENT_TYPE, buf); printf("client # %s\n", buf); printf("please enter: "); fflush(stdout); //From standard input to buffer ssize_t s = read(0, buf, sizeof(buf)); if(s > 0) { buf[s-1] = 0; //Sending Buffer Content to Client sendMsg(msgid, SERVER_TYPE, buf); printf("send done...\n"); } } //Server-side creation, server-side destruction of message queues destoryMsgQueue(msgid); return 0; }
client.c
#include "comm.h" int main() { //Open message queue int msgid = getMsgQueue(); //buffer char buf[1024]; while(1) { buf[0] = 0; printf("please enter:"); fflush(stdout); //From standard input to buffer ssize_t s = read(0, buf, sizeof(buf)); if(s>0) { buf[s-1] = 0; //Send buffers to servers sendMsg(msgid, CLIENT_TYPE, buf); printf("send done...\n"); } //Accept the server's response recvMsg(msgid, SERVER_TYPE, buf); printf("Server : %s\n", buf); } return 0; }
Operation results:
