Click here to Skip to main content
1,837 members
Articles / Security / MFC
Article

Round Trip Messaging with SAFMQ

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
12 Apr 2012 6K  
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:

// safmq_rt_client.cpp
// Sample round trip client.
 
#include <iostream>
#include "safmq.h"
#include "lib/MessageQueue.h"
#include "lib/MQFactory.h"
 
using namespace std;
using namespace safmq;
 
int main(int argc, char* argv[])
{
 QueueMessage     query, response;

 try {
     MessageQueue* query_que = 
       MQFactory::BuildQueueConnection("safmq:" 
       "//user:password@localhost/query","","");
     MessageQueue* response_que = 
       MQFactory::BuildQueueConnection("safmq:" 
       "//user:password@localhost/response","","");


     // build our request message, specify
     // the query must be received in 5 seconds
     query.setTimeToLiveSeconds(5);
     //Note: without the next line,
     // we won't be notified of timeouts
     query.setTTLErrorWanted(true);

     // Tell the responder where to send the responses
     query.setResponseQueueName("safmq" 
                "://localhost/resposne");

     // Build the body of the query.
     query.setBodyType(BT_TEXT);
     *query.getBufferStream() << "Hello";
     query.setLabel("query");

     // send the request
     ErrorCode        ec = query_que->Enqueue(query);
     if (ec == EC_NOERROR) {
        uuid id = query.getMessageID();
 
       // Look for a response, retreive
       // the body, for message with "id", 
       // wait an infinite amount of time
       // and place the result in "resposne"
       ec = response_que->RetrieveID(true, 
                             id,-1,response);
       if (ec == EC_NOERROR) {
               
         if (response.getMessageClass() == 
                       MC_SYSTEMERRMSG) {
           // We received a system error
           // message, probably a timeout
           cerr << response.getLabel() << endl;
         } else {
         // Output the result.
         cout << response.getBufferStream()->rdbuf() 
              << endl;
       }
     } else {
       cerr << "Retreiving the result gave ErrorCode:" 
            << ec << endl;
     }
   } else {
     cerr << "Sending the query gave ErrorCode:" 
          << ec << endl;
   }

   // Release the instance of the queue
   delete query_que;
   delete response_que;
 } catch (ErrorCode e) {
   cerr << "ErrorCode: " << e 
        << " received." << endl;
 } catch (exception& e) {
   cerr << e.what() << endl;
 }
 return 0;
}
 

////////////////////////////////////////////////
////////////////////////////////////////////////
 
// rt_server.cpp
// Sample Round Trip Server
 
#include <iostream>
#include <string>
#include "safmq.h"
#include "lib/MessageQueue.h"
#include "lib/MQFactory.h"
 
using namespace std;
using namespace safmq;
 
int main(int argc, char* argv[])
{
 QueueMessage     query, response;

 try {
     MessageQueue* query_que = 
        MQFactory::BuildQueueConnection("safmq:" 
        "//user:password@localhost/query","","");
     MessageQueue* response_que = NULL;
     SAFMQ_WSTRING response_name;

     // Retreive the query
     ErrorCode ec = query_que->Retrieve(true,-1,query);

     if (ec == EC_NOERROR) {
          // Create a response message
          response.setLabel("response");
          // tie the response to the
          // request with the ReciptID

          response.setReciptID(query.getMessageID());
          response.setBodyType(BT_TEXT);
          *response.getBufferStream() << "Hi!" 
                                      << endl;

          // Get and open the queue
          // that is the response queue
          response.getResponseQueueName(response_name);

          response_que = 
            MQFactory::BuildQueueConnection(response_name, 
            "user","password");
          
          // Send the response
          response_que->Enqueue(response);

          delete response_que;
     }

     // Release the instance of the queue
     delete query_que;
 } catch (ErrorCode e) {
         cerr << "ErrorCode: " << e 
              << " received." << endl;
 } catch (exception& e) {
         cerr << e.what() << endl;
 }
 return 0;
}

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


Written By
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 --