5,548,129 members and growing! (17,926 online)
Email Password   helpLost your password?
General Programming » Internet / Network » MSMQ     Intermediate

Round Trip Messaging with SAFMQ

By mattbattey

Describes the process for implementing a round trip, query-response message interaction with SAFMQ.
VC6, C++Windows, NT4, MFC, VS6, Visual Studio, Dev

Posted: 24 Jan 2006
Updated: 24 Jan 2006
Views: 9,463
Bookmarked: 11 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
4 votes for this Article.
Popularity: 2.48 Rating: 4.13 out of 5
0 votes, 0.0%
1
1 vote, 25.0%
2
0 votes, 0.0%
3
1 vote, 25.0%
4
2 votes, 50.0%
5

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:

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

About the Author

mattbattey


A programmer for 20 years and professionaly employed for 12, I am currently Cheif Engineer for Pharmacy Chare Professionals, Inc., located in Omaha, NE.

My experience is in the area of OO Design, Application, and programming, technical team leadership, RDBMS applications, ISAM applications, Image Processing, Mathematical image generation, Client-Server business applications, eBusiness applications, XML & EDI B2B communications, Java application development, C/C++ application development, CFML/ASP/VB development, on systems like Win2K/NT/98/95, Linux, Irix, Solaris, and MacOS.
Occupation: Architect
Location: United States United States

Other popular Internet / Network articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 2 of 2 (Total in Forum: 2) (Refresh)FirstPrevNext
Subject  Author Date 
QuestionGetting the response_name in the server programmemberitowi7:25 5 Feb '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 24 Jan 2006
Editor: Smitha Vijayan
Copyright 2006 by mattbattey
Everything else Copyright © CodeProject, 1999-2008
Web12 | Advertise on the Code Project