-- see section 15.7 of advanced programming in unix environment for details
At the end of section 15.7 of advanced programming in UNIX environment, the advantages and disadvantages of message queuing are summarized. The conclusion is that they should no longer be used in new applications. Indeed, in pursuit of efficiency, we can use shared memory, and in pursuit of convenience, we can use pipes or UNIX domains. Message queuing is in such an awkward position.
correlation function
#include <sys/msg.h> /* Used to create and access a message queue key: Like other IPC mechanisms, a program must provide a key to name a particular message queue msg: flg Is a permission flag indicating the access permission of the message queue, which is the same as the access permission of the file Return value: returns the identifier (non-zero integer) of a message queue named after key, and returns - 1 in case of failure. */ int msgget(key_t key, int msgflg); /* Used to add messages to the message queue msgid: Is the message queue identifier returned by the msgget function. msg_ptr: msg_ptr Is a pointer to the message to be sent msg_sz: It is the length of the message pointed to by msg_ptr. Note that it is the length of the message, not the length of the whole structure. That is to say, msg_sz is the length of the member variable excluding the long integer message type. msgflg: Used to control what happens when the current message queue is full or when a queued message reaches a system wide limit Return value: success, a copy of the message data will be put into the message queue, and 0 will be returned, and - 1 will be returned in case of failure. */ int msgsnd(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg); /*Used to get messages from a message queue msgid: Is the message queue identifier returned by the msgget function. msg_ptr: msg_ptr Is a pointer to the message to be sent msg_st: Ditto msgtype: A simple receive priority can be implemented. If msgtype is 0, the first message in the queue is obtained. If its value is greater than zero, the first information with the same message type is obtained. If it is less than zero, the first message of type equal to or less than the absolute value of msgtype is obtained. msgflg: Used to control what happens when there is no message of the corresponding type in the queue to receive Return value: upon success, the function returns the number of bytes put into the receive buffer, the message is copied to the user allocated buffer pointed by msg_ptr, and then the corresponding message in the message queue is deleted. Return - 1 on failure. */ int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg); /* Used to control message queues, similar to the shmctl function of shared memory msgid: Is the message queue identifier returned by the msgget function. Command: Is the action to be taken. It can take three values. IPC_STAT: Set the data in msgid UDS structure to the current association value of message queue, that is, overwrite the value of msgid UDS with the current association value of message queue. IPC_SET: If the process has sufficient permissions, set the current associated value of the message queue to the value given in the msgid? DS structure IPC_RMID: Delete message queue buf: Is a pointer to the msgid? DS structure, which points to the message queuing mode and access rights structure. The msgid? DS structure includes at least the following members: struct msgid_ds { uid_t shm_perm.uid; uid_t shm_perm.gid; mode_t shm_perm.mode; }; Return value: 0 for success and - 1 for failure. */ int msgctl(int msgid, int command, struct msgid_ds *buf);
Example
Communication between client and server
//comm.h #ifndef _COMM_H_ #define _COMM_H_ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ipc.h> #include <sys/types.h> #include <sys/msg.h> struct msgbuf { long mtype; char mtext[1024]; }; #define SERVER_TYPE 1 #define CLIENT_TYPE 2 int createMsgQueue(); int getMsgQueue(); int destoryMsgQueue(int msg_id); int sendMsgQueue(int msg_id, int who, char* msg); int recvMsgQueue(int msg_id, int recvType, char out[]); #endif
//comm.c #include "comm.h" static int commMsgQueue(int flags) { key_t key = ftok("/tmp", 0x6666); if(key < 0) { perror("ftok"); return -1; } int msg_id = msgget(key, flags); if(msg_id < 0) { perror("msgget"); } return msg_id; } int createMsgQueue() { return commMsgQueue(IPC_CREAT|IPC_EXCL|0666); } int getMsgQueue() { return commMsgQueue(IPC_CREAT); } int destoryMsgQueue(int msg_id) { if(msgctl(msg_id, IPC_RMID, NULL) < 0) { perror("msgctl"); return -1; } return 0; } int sendMsgQueue(int msg_id, int who, char* msg) { struct msgbuf buf; buf.mtype = who; strcpy(buf.mtext, msg); if(msgsnd(msg_id, (void*)&buf, sizeof(buf.mtext), 0) < 0) { perror("msgsnd"); return -1; } return 0; } int recvMsgQueue(int msg_id, int recvType, char out[]) { struct msgbuf buf; int size=sizeof(buf.mtext); if(msgrcv(msg_id, (void*)&buf, size, recvType, 0) < 0) { perror("msgrcv"); return -1; } strncpy(out, buf.mtext, size); out[size] = 0; return 0; }
//server.c #include "comm.h" int main() { int msgid = createMsgQueue(); char buf[1024] = {0}; while(1) { recvMsgQueue(msgid, CLIENT_TYPE, buf); if(strcasecmp("quit", buf) == 0) break; printf("client# %s\n", buf); printf("Please enter# "); fflush(stdout); ssize_t s = read(0, buf, sizeof(buf)); if(s>0) { buf[s-1]=0; sendMsgQueue(msgid, SERVER_TYPE, buf); printf("send done, wait recv...\n"); } } destoryMsgQueue(msgid); return 0; }
//client.c #include "comm.h" int main() { int msgid = getMsgQueue(); char buf[1024] = {0}; while(1) { printf("Please Enter# "); fflush(stdout); ssize_t s = read(0, buf, sizeof(buf)); if(s > 0) { buf[s-1]=0; sendMsgQueue(msgid, CLIENT_TYPE, buf); if(strcasecmp("quit", buf) == 0) break; printf("send done, wait recv...\n"); } recvMsgQueue(msgid, SERVER_TYPE, buf); printf("server# %s\n", buf); } return 0; }
Operation result
root@jonathan-pc:~/test/msg# ls client.c comm.c comm.h server.c root@jonathan-pc:~/test/msg# gcc client.c comm.c -o c root@jonathan-pc:~/test/msg# gcc server.c comm.c -o s root@jonathan-pc:~/test/msg# ./s client# hello Please enter# nihao send done, wait recv... root@jonathan-pc:~/test/msg#
root@jonathan-pc:~/test/msg# ./c Please Enter# hello send done, wait recv... nihaoserver# nihao Please Enter# quit send done, wait recv...