C++ || Snippet – How To Use Message Queues For Interprocess Communication
The following is sample code which demonstrates the use of the msgsnd, msgrcv, and msgget function calls for use with message queues on Unix based systems.
Message queues are used for interprocess communication. They provide two (or more) separate programs (i.e: sender and receiver) with the ability to interact with eachother. This is ideal because the sender and receiver do not need to interact with the message queue at the same time. Messages can be sent at one point in time, be placed on the queue until the receiver is ready for it, and then be removed at another point in time when the program(s) that service the queue are finally ready to receive a message.
This concept is different from threaded and forked process IPC procedures, which often times process data in a more streamlined manner. Rather than following a strict pattern as to when data is to be sent and received, queuing is a mechanism in which messages are held until the receiving application is ready to process them.
The example on this page demonstrates the above use of a message queue to transfer data between two separate programs. The sending program (client.cpp) sends an integer and string variable to the receiving program (server.cpp), which then displays that received data to the screen.
NOTE: The server program must be ran before the client program!
=== 1. Server.cpp (Receiver) ===
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
// ============================================================================ // Author: Kenneth Perkins // Date: Oct 4, 2013 // Taken From: http://programmingnotes.org/ // File: Server.cpp // Description: Demonstrate the use of a message queue for interprocess // communication. This program illustrates the server (receiving) end of // the message queue. // ============================================================================ #include <iostream> #include <cstdlib> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> using namespace std; // Compile & Run // g++ Server.cpp -o Server // ./Server // the structure representing the message queue // & must match the same layout as in the client.cpp struct MsgQueue { // IMPORTANT: every message structure must start with this long messageType; // these variables are optional & you can add // more or less if you wish int someNumber; char buff[100]; }; // message queue flag const int MSG_Q_KEY_FLAG = 0664; // message queue data transfer channel const int MSG_Q_CHANNEL = 26; int main() { // declare variables key_t key = -1; int msqid = -1; MsgQueue msg; // use a random file and a random character to generate // a unique key. The same parameters to this function will // always generate the same value. This is how multiple // processes can connect to the same queue. key = ftok("/bin/ls", 'K'); // was the key allocation successful ? if(key < 0) { perror("ftok error"); exit(1); } // allocate the message queue if it does not already exist. // this function returns the id of the queue. msqid = msgget(key, MSG_Q_KEY_FLAG | IPC_CREAT); // was the allocation a success ? if(msqid < 0) { perror("msgget"); exit(1); } // display info to the screen cout <<"\nThe server has started!\n" <<"\nWaiting for someone to connect to server id #"<<msqid<<" with " <<"the key "<<key<<endl<<endl; // recieve 10 messages from the client for(int x = 0; x < 10; ++x) { // this is where we receive messages: // @param: msqid - the id of the message queue // @param: msg - the message structure which stores the // received message // @param: sizeof(msg) - sizeof(long) - size of the message // excluding the required first member (messageType) which is // required. // @param: MSG_Q_CHANNEL - receive all messages whose type parameter // is set equal to "MSG_Q_CHANNEL" // @param: 0 - flag values (not useful for this example). if(msgrcv(msqid, &msg, sizeof(msg) - sizeof(long), MSG_Q_CHANNEL, 0) < 0) { perror("msgrcv"); exit(1); } // print the received message from the client cout << "someNumber = "<<msg.someNumber<<" buff = "<<msg.buff<<endl; } // finally, deallocate the message queue if(msgctl(msqid, IPC_RMID, NULL) < 0) { perror("msgctl"); exit(1); } cout << "\nServer is now shutting down!\n"; return 0; }// http://programmingnotes.org/ |
=== 2. Client.cpp (Sender) ===
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
// ============================================================================ // Author: Kenneth Perkins // Date: Oct 4, 2013 // Taken From: http://programmingnotes.org/ // File: Client.cpp // Description: Demonstrate the use of a message queue for interprocess // communication. This program illustrates the client (sending) end of // the message queue // ============================================================================ #include <iostream> #include <cstdlib> #include <cstring> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> using namespace std; // Compile & Run // g++ Client.cpp -o Client // ./Client // the structure representing the message queue // & must match the same layout as in the server.cpp struct MsgQueue { // IMPORTANT: every message structure must start with this long messageType; // these variables are optional & you can add // more or less if you wish int someNumber; char buff[100]; }; // message queue flag const int MSG_Q_KEY_FLAG = 0664; // message queue type const int MSG_Q_CHANNEL = 26; int main() { // declare variables key_t key = -1; int msqid = -1; MsgQueue msg; // use a random file and a random character to generate // a unique key. The same parameters to this function will // always generate the same value. This is how multiple // processes can connect to the same queue. key = ftok("/bin/ls", 'K'); // was the key allocation successful ? if(key < 0) { perror("ftok"); exit(1); } // connect to the message queue; fail if the // there is no message queue associated with // this key. This function returns the id of // the queue. msqid = msgget(key, MSG_Q_KEY_FLAG); // was the allocation a success ? if(msqid < 0) { perror("msgget"); exit(1); } // display info to the screen cout <<"\nSuccessfully connected to server id #"<<msqid<<" with " <<"the key "<<key <<"\n\nNow sending messages...."; // send 10 messages to the server for(int x = 0; x < 10; ++x) { // set the message type - this must match // the 4th parameter of msgrcv() in the server.cpp code msg.messageType = MSG_Q_CHANNEL; // place data into the message queue structure to send to the server msg.someNumber = x; strncpy(msg.buff, "Message queues are awesome!", sizeof(msg.buff)); // this is where we send messages: // @param: msqid - the id of the message queue // @param: msg - the message structure which stores the // message to send // @param: sizeof(msg) - sizeof(long) - size of the message // excluding the required first member (messageType) which is // required. // @param: 0 - flag values (not useful for this example). if(msgsnd(msqid, &msg, sizeof(msg) - sizeof(long), 0) < 0) { perror("msgsnd"); exit(1); } } cout << "Sending complete!\n"; return 0; }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
You can view all allocated message queues using the ipcs command. You can delete a message queue from command line using ipcrm -q [KEY SHOWN BY IPCS]. Message queues are a finite resource. If something goes wrong during the execution of your program, you must manually delete all your queues.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
The following is sample output.
SERVER OUTPUT:
The server has started!
Waiting for someone to connect to server id #753664 with the key 1258295474
someNumber = 0 buff = Message queues are awesome!
someNumber = 1 buff = Message queues are awesome!
someNumber = 2 buff = Message queues are awesome!
someNumber = 3 buff = Message queues are awesome!
someNumber = 4 buff = Message queues are awesome!
someNumber = 5 buff = Message queues are awesome!
someNumber = 6 buff = Message queues are awesome!
someNumber = 7 buff = Message queues are awesome!
someNumber = 8 buff = Message queues are awesome!
someNumber = 9 buff = Message queues are awesome!Server is now shutting down!
CLIENT OUTPUT:
Successfully connected to server id #753664 with the key 1258295474
Now sending messages....Sending complete!
Leave a Reply