Message Queue Class

Table of contents:

As the functionality of and syntax for message queues is somewhat complex, they are ideal candidates for incorporation into a C++ class. A message queue class would define the relationships between message queue data and the functions ( methods ) that manipulate this data. A declaration of a simplified message queue class called Message_que is shown in Figure 6.10.

Figure 6.10 Header file for a basic message queue class.

File : Message_que.h
 /*
 A VERY simplified message queue class for use in a std UNIX
 environment. See the text for instructions on how to use
 this class. Copyright (c) 2002 J. S. Gray
 +
 Exit codes for class operations:
 
 1 - Unable to create queue 2 - Cannot access queue
 3 - Enque has failed 4 - Deque has failed
 10 5 - Unable to remove queue
 */
 #ifndef Message_que_h
 #define Message_que_h
 #define _GNU_SOURCE
 + #include 
 #include 
 #include 
 #include 
 #include 
 20 #include 
 #include 
 
 class Message_que {
 public:
 + Message_que (const char ='M'); // Constructor
 void Remove( ); // Remove the queue
 void Enque( void *, int ); // Place a message in the queue
 int Deque( void *, int, int ); // Obtain a message from queue
 bool Exist( const char ='M' ); // True if the queue exists
 30 void Create( ); // Create the queue
 void Acquire( ); // Acquire access to the queue
 private:
 int msqid; // ID of message queue
 key_t ipckey; // Key from ftok
 + };
 #endif

As defined, the Message_que class has seven public methods and three private data members . The functionality of each method is shown in Table 6.14.

The C++ code that implements the message queue class is found in the program file Message_que.cxx (Program 6.5). As shown, the code is bare boneslittle is done to handle errors, and only basic message queue functionality is addressed.

Table 6.14. Message_que Class Methods.

Method name

Explanation

Message_que

This is the class constructor. This method takes one argument, which, if specified, defaults to the value M . The constructor generates the message queue ID.

Remove

This method removes the message queue from the system.

Enque

Enque is used to add a message to the message queue. This method is passed a reference to the message and the message size (in bytes).

Deque

The Deque method removes a single message from the message queue. This method has three arguments: a reference to a structure to store the returned data, the maximum size of a returned message, and the message type.

Exist

This method returns a true or false as to whether or not the message queue exists.

Create

Create (generate) a new message queue.

Acquire

Gains access to the existing message queue.

Program 6.5a Program code for the Message Queue Class.

File : Message_que.cxx
 /*
 Message queue implementationCopyright (c) 2002 J. S. Gray
 */
 #include "Message_que.h"
 + #include 
 
 // Message queue constructor.
 Message_que::Message_que( const char the_key ){
 ipckey = ftok( ".", the_key );
 10 msqid = -1;
 }
 // Remove the message queue (if this process created it)
 void
 Message_que::Remove( ) {
 + if ( msgctl( msqid, IPC_RMID, (struct msqid_ds *) 0 ) == -1 )
 exit( 5 );
 }
 // Place a message in the message queue.
 void
 20 Message_que::Enque( void *msg, int msg_size ){
 if ( msgsnd( msqid, msg, msg_size, 0 ) == -1 )
 exit( 3 );
 }
 // Return a message from the message queue.
 + int
 Message_que::Deque( void *msg, int msg_size, int msg_type ){
 int n;
 memset( msg, 0x0, msg_size ); // clear space
 if ( (n=msgrcv( msqid, msg, msg_size, msg_type, IPC_NOWAIT)) == -1 )
 30 exit( 4 );
 return n;
 }
 // True if message queue exists else false.
 bool
 + Message_que::Exist( const char the_key ){
 return (msgget(ipckey, 0) != -1);
 }
 // Generate a new message queue.
 void
 40 Message_que::Create( ){
 if ( (msqid=msgget(ipckey, IPC_CREAT0660)) == -1 )
 exit( 1 );
 }
 // Acquire (gain access to) existing message queue.
 + void
 Message_que::Acquire( ){
 if ( (msqid=msgget(ipckey, 0)) == -1 )
 exit( 2 );
 }

To use this class, the files Message_que.h and Message_que.cxx should reside locally. The Message_que class is compiled into object code with the command line

linux$ g++ Message_que.cxx c

At the top of the source file that will use a Message_que object, add the statement

#include "Message_que.h"

to make the class definition available to the compiler. When compiling the source file, include the message queue object code file

linux$ g++ your_file_name.cxx Message_que.o

Program 6.6 demonstrates the use of a message queue object. This program allows command-line manipulation of a message queue. As such, the message queue could be used as a drop off and retrieval site for messages.

Program 6.6 A command-line message queue manipulation utility.

File : p6.6.cxx
 /*
 A message queue manipulation utility
 */
 #include "Message_que.h"

<-- 1

+ #include 
 #include 
 #include 
 using namespace std;
 
 10 typedef struct {
 long int m_type;
 char m_text[1024];
 } MESSAGE;
 extern char *optarg;
 + extern int optind, opterr, optopt;
 int
 main(int argc, char *argv[ ]){
 int c;
 char optstring[] = "sri:m:";

<-- 2

20 opterr = 0;
 bool snd_msg=false, get_msg=false, rmv_que=false;
 char *the_message;
 // Allocate msg - clear text
 MESSAGE my_msg;
 + memset( my_msg.m_text, 0x0, 1024 );
 // Allocate - acquire msg queue
 Message_que MQ('M');
 if ( !MQ.Exist('M') )
 MQ.Create( );
 30 else
 MQ.Acquire( );
 // Process command line args
 while ((c = getopt(argc, argv, optstring)) != -1)
 switch (c) {
 + case 's':
 snd_msg=true;
 break;
 case 'r':
 get_msg=true;
 40 break;
 case 'i':
 my_msg.m_type=atol(optarg);
 break;

<-- 3

case 'm':
 + strcpy(my_msg.m_text,optarg);
 }
 if ( snd_msg && my_msg.m_type > 0 ){
 MQ.Enque( &my_msg, strlen(my_msg.m_text)+1);
 cerr << "Added : " << my_msg.m_text << endl;
 50 } else if ( get_msg && my_msg.m_type > 0 ){
 MQ.Deque(&my_msg, 1024, my_msg.m_type);
 cerr << "Message: " << my_msg.m_text << endl;
 } else
 cerr << "Invalid command line option(s)" << endl;
 + return 0;
 }

(1) Include the Message_que class definition.

(2) Acceptable command-line options :

(3) Use the optarg reference to obtain the actual command-line data.

In line 4 of the program, the definition of the Message_que class is included. At line 10, the format of a message queue message is defined. Within the function main , the acceptable command-line options are assigned to the optstring array. The program accepts two standard-format command-line options. The -s option indicates a message is to be sent to the message queue, while r means a message should be read from the message queue. Theremaining two options of the program require arguments. The i option is to be followed with the message queue ID (type), and the m option is to be followed with an actual message. If the message is more than one word, it should be surrounded with quotes.

A while loop and the getopt library function are used to parse command-line options. If the user indicates a message is to be sent, the message type ( i ) and the actual message ( -m ) must be specified. If a message is to be retrieved, then just the message type ( -i ) must be indicated. The program informs the user of its activity, including a message that indicates when an improper set of command-line options has been passed. Figure 6.11 demonstrates the use of Program 6.6.

Figure 6.11 Manipulating a message queue from the command line.

linux$ ipcs -q
------ Message Queues ------

<-- 1

key msqid owner perms used-bytes messages

linux$ p6.6 -i 98 -s -m "Don't forget the fish!"

<-- 2

Added : Don't forget the fish!

linux$ p6.6 -i 98 -s -m "See you Wednesday -jg

<-- 2

Added : See you Wednesday -jg

linux$ p6.6 -s -i 72 -m "Paper due on the 16th"

<-- 2

Added : Paper due on the 16th

linux$ ipcs -q
------ Message Queues ------

<-- 2

key msqid owner perms used-bytes messages
0x4d15ae86 4718592 gray 660 67 3
linux$ p6.6 -r -i 98
Message: Don't forget the fish!

<-- 3

linux$ p6.6 -r -i 98
Message: See you wednesday -jg

linux$ ipcs -q
------ Message Queues ------
key msqid owner perms used-bytes messages
0x4d15ae86 4718592 gray 660 22 1

linux$ ipcs -q -i 4718592
Message Queue msqid=4718592

<-- 4

uid=500 gid=1000 cuid=500 cgid=1000 mode=0660
cbytes=22 qbytes=16384 qnum=1 lspid=17306 lrpid=17309
send_time=Sun Mar 10 17:06:40 2002
rcv_time=Sun Mar 10 17:06:40 2002
change_time=Sun Mar 10 17:06:40 2002

(1) At the start, no message queues in the system.

(2) Add some messages to the message queue.

(2) Three messages now in the queue.

(3) Retrieve the first two messages of type 98.

(4) What the system knows about this message queue.

EXERCISE

Program 6.6 has a great deal of room for improvement. For example, when a message is retrieved, it is removed from the message queue. In addition, the user is unable to remove the message queue (without resorting to the ipcrm command). Modify Program 6.6 to support the nondestructive reading of messages and the removal of the message queue from the system.

EXERCISE

Modify the clientserver programs to implement a rudimentary chat program that allows users to interactively talk to one another ( sort of a poor man's talk ). One way to do this is to have the server examine the first character of the text portion of a SERVER message. If the character is, say, a " . ", then the message is assumed to be a command the server should act on. For example, if the sequence is .lo , then the server records the PID of the client as logged in. If the sequence is .who , the server returns the list of the PIDs of all logged-in (attached) clients . The PID information can then be used to connect the two processes so that interactive communication can occur.

Programs and Processes

Processing Environment

Using Processes

Primitive Communications

Pipes

Message Queues

Semaphores

Shared Memory

Remote Procedure Calls

Sockets

Threads

Appendix A. Using Linux Manual Pages

Appendix B. UNIX Error Messages

Appendix C. RPC Syntax Diagrams

Appendix D. Profiling Programs



Interprocess Communication in Linux
Interprocess Communications in Linux: The Nooks and Crannies
ISBN: 0130460427
EAN: 2147483647
Year: 2001
Pages: 136

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net