Click here to Skip to main content
1,078 members
Articles / Security / MFC
Article
Posted 12 Apr 2012

Tagged as

Stats

4.7K views

Round Trip Messaging with SAFMQ

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
12 Apr 2012
Describes the process for implementing a round trip, query-response message interaction with SAFMQ.

This article is a sponsored article. Articles such as these are intended to provide you with information on products and services that we consider useful and of value to developers

Introduction

Query-response applications are very important in computer technology. We use them every day. In fact, you are using one now as you read this article. Your web browser sent a query to the servers at www.codeproject.com, it received the response in the form of text encoded as HTML, which your browser displays to you right now. Query-response applications aren’t just for the web, but for accessing a database server, or receiving files from a file server; even creating users in Windows 2000 and Windows XP uses a query response architecture.

SAFMQ is really a type of middleware, or software that works between two applications so they can communicate with each other. Although SAFMQ has Store and Forward Message Queuing, it also is tuned for query-response applications. Each message enqueued in the SAFMQ server is given a unique UUID (also known as GUID). This value is based off the MAC address of the server and the date and time it was created, (down to the millisecond) using RFC 4122 on UNIX systems, and Microsoft’s implementation on Windows based systems. This UUID is available to both the sender of the message and the receiver. In addition to the automatically generated UUID, a message also has a “Receipt ID,” which can be specified by the sender. Receivers can call a special version of Retrieve which specifies a Receipt ID, and causes the caller to wait until a message is retrievable with a matching Receipt ID.

Here’s a collaboration diagram that may help describe the Round-Trip Query-Response architecture:

Image 1

Now, there are some special features that you can use with Round-Trip messaging. One is the ability to specify the amount of time a message may live on a queue. This value known as “Time To Live” tells the SAFMQ server to automatically remove the message from the queue if it has been on the queue too long. Also, a client can request that it be notified when a message expires, and the SAFMQ server will generate a response message in this case.

Background

If you aren’t familiar with SAFMQ, you can find out more about it here.

Using the code

Here’s a sample server and client:

  1  // safmq_rt_client.cpp
  2  // Sample round trip client.
  3   
  4  #include <iostream>
  5  #include "safmq.h"
  6  #include "lib/MessageQueue.h"
  7  #include "lib/MQFactory.h"
  8   
  9  using namespace std;
 10  using namespace safmq;
 11   
 12  int main(int argc, char* argv[])
 13  {
 14   QueueMessage     query, response;
 15  
 16   try {
 17       MessageQueue* query_que = 
 18         MQFactory::BuildQueueConnection("safmq:" 
 19         "//user:password@localhost/query","","");
 20       MessageQueue* response_que = 
 21         MQFactory::BuildQueueConnection("safmq:" 
 22         "//user:password@localhost/response","","");
 23  
 24  
 25       // build our request message, specify
 26       // the query must be received in 5 seconds
 27       query.setTimeToLiveSeconds(5);
 28       //Note: without the next line,
 29       // we won't be notified of timeouts
 30       query.setTTLErrorWanted(true);
 31  
 32       // Tell the responder where to send the responses
 33       query.setResponseQueueName("safmq" 
 34                  "://localhost/resposne");
 35  
 36       // Build the body of the query.
 37       query.setBodyType(BT_TEXT);
 38       *query.getBufferStream() << "Hello";
 39       query.setLabel("query");
 40  
 41       // send the request
 42       ErrorCode        ec = query_que->Enqueue(query);
 43       if (ec == EC_NOERROR) {
 44          uuid id = query.getMessageID();
 45   
 46         // Look for a response, retreive
 47         // the body, for message with "id", 
 48         // wait an infinite amount of time
 49         // and place the result in "resposne"
 50         ec = response_que->RetrieveID(true, 
 51                               id,-1,response);
 52         if (ec == EC_NOERROR) {
 53                 
 54           if (response.getMessageClass() == 
 55                         MC_SYSTEMERRMSG) {
 56             // We received a system error
 57             // message, probably a timeout
 58             cerr << response.getLabel() << endl;
 59           } else {
 60           // Output the result.
 61           cout << response.getBufferStream()->rdbuf() 
 62                << endl;
 63         }
 64       } else {
 65         cerr << "Retreiving the result gave ErrorCode:" 
 66              << ec << endl;
 67       }
 68     } else {
 69       cerr << "Sending the query gave ErrorCode:" 
 70            << ec << endl;
 71     }
 72  
 73     // Release the instance of the queue
 74     delete query_que;
 75     delete response_que;
 76   } catch (ErrorCode e) {
 77     cerr << "ErrorCode: " << e 
 78          << " received." << endl;
 79   } catch (exception& e) {
 80     cerr << e.what() << endl;
 81   }
 82   return 0;
 83  }
 84   
 85  
 86  ////////////////////////////////////////////////
 87  ////////////////////////////////////////////////
 88   
 89  // rt_server.cpp
 90  // Sample Round Trip Server
 91   
 92  #include <iostream>
 93  #include <string>
 94  #include "safmq.h"
 95  #include "lib/MessageQueue.h"
 96  #include "lib/MQFactory.h"
 97   
 98  using namespace std;
 99  using namespace safmq;
100   
101  int main(int argc, char* argv[])
102  {
103   QueueMessage     query, response;
104  
105   try {
106       MessageQueue* query_que = 
107          MQFactory::BuildQueueConnection("safmq:" 
108          "//user:password@localhost/query","","");
109       MessageQueue* response_que = NULL;
110       SAFMQ_WSTRING response_name;
111  
112       // Retreive the query
113       ErrorCode ec = query_que->Retrieve(true,-1,query);
114  
115       if (ec == EC_NOERROR) {
116            // Create a response message
117            response.setLabel("response");
118            // tie the response to the
119            // request with the ReciptID
120  
121            response.setReciptID(query.getMessageID());
122            response.setBodyType(BT_TEXT);
123            *response.getBufferStream() << "Hi!" 
124                                        << endl;
125  
126            // Get and open the queue
127            // that is the response queue
128            response.getResponseQueueName(response_name);
129  
130            response_que = 
131              MQFactory::BuildQueueConnection(response_name, 
132              "user","password");
133            
134            // Send the response
135            response_que->Enqueue(response);
136  
137            delete response_que;
138       }
139  
140       // Release the instance of the queue
141       delete query_que;
142   } catch (ErrorCode e) {
143           cerr << "ErrorCode: " << e 
144                << " received." << endl;
145   } catch (exception& e) {
146           cerr << e.what() << endl;
147   }
148   return 0;
149  }

History

Updates and documentation for SAFMQ can be found at SourceForge.net.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

mattbattey
Architect
United States United States
This member doesn't quite have enough reputation to be able to display their biography and homepage.

Comments and Discussions

 
-- There are no messages in this forum --