Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 软件时空 > 软件相关 > Developing WebSphere MQ Client Applications in C++
【标  题】:Developing WebSphere MQ Client Applications in C++
【关键字】:Developing,WebSphere,MQ,Client,Applications,in,C++
【来  源】:http://www.cublog.cn/u/22208/showart.php?id=159452

Developing WebSphere MQ Client Applications in C++

Your Ad Here

WebSphere MQ/MQSeries client software is distributed as a part of WebSphere MQ suite and it can also be downloaded for FREE from IBM for various platforms. A WebSphere MQ client application interacts with one or more queue managers through MQI channels (such as server-connection channel and client-connection channel) using a communications protocol. The client application executes in synchronous mode since the client doesn't host any transmission queues or communication channels (such as sender-channel and receiver-channel). The client connects to a queue manager by issuing a MQCONN or MQCONNX call and it stays connected to the queue manager until is issues a MQDISC call. It is possible to connect to multiple queue managers concurrently in a single thread of your MQ client application.

The client applications are written using MQI in C, C++, Java, COBOL, Visual Basic and PL/I languages (not all languages are supported on all platforms). In this article, I will explain how to develop a simple WebSphere MQ client application using the C++ classes supplied with the WebSphere MQ. These classes simplify the usage of various MQSeries data structures and objects. Yes, you no longer have to manage the size of the message buffers :)

In the following sections, we will develop a simple client application that connects to a queue manager (named QM1) and opens two queues (named IN and OUT). It gets a message from one queue (IN) and posts it to another queue (OUT). The communication protocol of our choice is TCP/IP.

For the description of the various classes required to develop this application, refer to the manual titled "Using C++". Here is the list of classes we will use:

  • ImqQueueManager: This class encapsulates a queue manager.
  • ImqChannel: This class encapsulates a channel definition (MQCD) for use during execution of the ImqQueueManager::connect() method.
  • ImqQueue: This class encapsulates a message queue.
  • ImqMessage: This class encapsulates an MQMD data structure, and also handles the construction and reconstruction of message data (see also ImqCache).
  • ImqGetMessageOptions and ImqPutMessageOptions: These classes encapsulate the MQGMO and MQPMO data structures respectively.

Before we go any further, a little note about the security - I am assuming an environment where the server connection channel on the server is setup with a valid MCA user id so that the server can accept all the messages coming through that channel. This is probably not a good setup for your organization. I am not going into the details of other security options such as user id authentication, security exits etc.

An important aspect of a client application development is to understand the various ways the connection parameters are provided to your program. There are there methods available and we will discuss each of them.

Method 1: Using the ImqChannel object

When you know the values of all the required connection parameters (Channel name, host name/IP, listener port number), we can initialize the ImqChannel object and use it to connect to the queue manager. The following code illustrates this method:

	#include <iostream>
	#include <string>
	#include <imqi.hpp>

	using namespace std;

	int main ( int argc, char * * argv ) {
		ImqQueueManager mgr;            // Queue manager
		ImqQueue in_queue, out_queue;   // Queues
		ImqChannel channel;             // Client connection channel
		ImqMessage msg;                 // Data message
		ImqGetMessageOptions gmo;       // GET message options
		ImqPutMessageOptions pmo;       // PUT message options

		if ( argc != 4 ) {
			cout<<"Usage: mqclient1 <Queue Manager> <Queue1> <Queue2>"<<endl;
			exit(0);
		}

		mgr.setName(argv[1]);
		in_queue.setName(argv[2]);
		out_queue.setName(argv[3]);
		mgr.setName();

		//Initialize channel values
		//Warning: hard-coded values
		channel.setChannelName("CHAN1");
		channel.setTransportType( MQXPT_TCP );
		channel.setConnectionName("10.40.60.68(1414)");

		//Associate this channel with the queue manager
		mgr.setChannelReference(channel);

		//Connect to the queue manager
		if ( !mgr.connect() ) {
			cout<<"ImqQueueManager::connect failed with reason code "
			<<(long)mgr.reasonCode( )<<endl;
			exit( (int)mgr.reasonCode() );
		}
		cout<<"Connected to the queue manager "<<(char *)mgr.name()<<endl;

		// Associate the queues with the queue manager.
		in_queue.setConnectionReference(mgr);
		out_queue.setConnectionReference(mgr);

		//Set Open queue options for GET
		in_queue.setOpenOptions(MQOO_INPUT_SHARED + MQOO_INQUIRE 
				+ MQOO_FAIL_IF_QUIESCING ); 

		if(!in_queue.open()) {
			cout<<"ImqQueue::open failed with reason code "
			<<(long)in_queue.reasonCode( )<<endl;
			exit( (int)in_queue.reasonCode() );
		}
		cout<<"Opened the queue(for GET): "<<(char *)in_queue.name()<<endl;

		//Set Open queue options for PUT
		out_queue.setOpenOptions(MQOO_OUTPUT + MQOO_INQUIRE  
				+ MQOO_FAIL_IF_QUIESCING);

		if( !out_queue.open()) {
			cout<<"ImqQueue::open failed with reason code "
			<<(long)out_queue.reasonCode( )<<endl;
			exit( (int)out_queue.reasonCode() );
		}
		cout<<"Opened the queue(for PUT): "<<(char *)out_queue.name()<<endl;

		//Prepare to GET and PUT the message
		gmo.setOptions( MQGMO_WAIT | MQGMO_FAIL_IF_QUIESCING );
		gmo.setWaitInterval( MQWI_UNLIMITED ); 
		pmo.setOptions(MQPMO_FAIL_IF_QUIESCING);

		//Since we are NOT looking for a specific message, 
		//set the message id and the correlation id to default values
		msg.setMessageId( );
		msg.setCorrelationId( );

		//Get a message from the queue
		if( !in_queue.get(msg, gmo) ) {
			cout<<"ImqQueue::get failed with reason code "
			<<(long)in_queue.reasonCode( )<<endl;
			exit( (int)in_queue.reasonCode() );
		}
		cout<<"Got the message....."<<endl;

		//We are ready to PUT the message
		if( !out_queue.put(msg, pmo) ) {
			cout<<"ImqQueue::put failed with reason code "
			<<(long)out_queue.reasonCode( )<<endl;
			exit( (int)out_queue.reasonCode() );
		}
		cout<<"Posted the message...."<<endl;

		return 0;
	}
	

In the code, the ImqChannel object is initialized with the hard-coded values.:

	//Initialize channel values
	//Warning: hard-coded values
	channel.setChannelName("CHAN1");
	channel.setTransportType( MQXPT_TCP );
	channel.setConnectionName("10.40.60.68(1414)");

	//Associate this channel with the queue manager
	mgr.setChannelReference(channel);
	

The following code snippet from the IBM sample programs demonstrates the initialization of ImqChannel object by parsing the connection parameters provided to the program as an argument in the format - "CHAN1/TCP/10.40.60.68(1414)"

	ImqString strParse(argv[4]); //example: argv[4] is "CHAN1/TCP/10.40.60.68(1414)"
	ImqString strToken ;

	ImqChannel channel;

	if ( strParse.cutOut( strToken, '/' ) ) {
		channel.setChannelName( strToken );

		if ( strParse.cutOut( strToken, '/' ) ) {

			// Interpret the transport type.
			if ( strToken.upperCase( ) == (ImqString)"LU62" ) {
				channel.setTransportType( MQXPT_LU62 );
			}
			if ( strToken.upperCase( ) == (ImqString)"NETBIOS" ) {
				channel.setTransportType( MQXPT_NETBIOS );
			}
			if ( strToken.upperCase( ) == (ImqString)"SPX" ) {
				channel.setTransportType( MQXPT_SPX );
			}
			if ( strToken.upperCase( ) == (ImqString)"TCP" ) {
				channel.setTransportType( MQXPT_TCP );
			}

			// Establish the connection name.
			if ( strParse.cutOut( strToken ) ) {
				channel.setConnectionName( strToken );
			}
		}
	}
	mgr.setChannelReference( channel );
	
Compiling and Running the program

To compile this program, link with appropriate client libraries. For example, On Windows2000, I linked with these libraries - imqc23vn.Lib and imqb23vn.Lib.

Before you execute the program, ensure that you have correct details of the client connection channel defined on the MQ Server you want to connect to. Execute the program with the command:

		mqclient1 QM1 IN OUT
	

where QM1 is the queue manager, IN is the queue from where the program gets a message and OUT is the queue to where the message is posted. The program waits till a messages arrives on IN queue. Post a message to IN queue and watch it appear on OUT queue. Successful execution of the program writes the following lines on the console:

	E:\MQSeries\Clients>mqclient1 QM1 IN OUT
	Connected to the queue manager QM1
	Opened the queue(for GET): IN
	Opened the queue(for PUT): OUT
	Got the message.....
	Posted the message....

	E:\MQSeries\Clients>
	

If you added the functionality to provide the connection parameters as an argument to the program, execute the program with the command:

		mqclient1 QM1 IN OUT CHAN1/TCP/10.40.60.68(1414)
	
Method 2: Using MQSERVER environment variable

If the environment variable MQSERVER is set, you can avoid using the ImqChannel object. MQSERVER variable is set in the following format:

MQSERVER=CHAN1/TCP/10.40.60.68(1414)

Since the MQSERVER environment variable has all the required connection parameters, ImqQueueManager::connect() call picks them automatically. Remove the refernces to ImqChannel object from the code presented above to use the MQSERVER environment variable.

Method 3: Using client channel definition table file

A client channel definition table file contains the details of all the client-connection channels defined at the WebSphere MQ Server. It is a binary file with the name amqclchl.tab and it is created automatically by the WebSphere MQ system when you create one or more client connection channels. You can find this file on the server at this location:

On Windows NT/2000/XP
<MQSeries Install>\mqm\qmgrs\<Queue Manager Name>\@ipcc

On UNIX systems
/var/mqm/qmgrs/<Queue Manager Name>/@ipcc

The client channel definition table file for the sample program we have been discussing is generated by creating the client connection channel named CHAN1 by running the following commands (using runmqsc utility) on the server (Note that client connection channel requires a server connection channel with the same name):

	DEFINE CHANNEL(CHAN1) CHLTYPE(SVRCONN) TRPTYPE(TCP) +
	DESCR('Server connection to MQSeries client')
 
	DEFINE CHANNEL(CHAN1) CHLTYPE(CLNTCONN) TRPTYPE(TCP) +
	CONNAME(10.40.60.68(1414)) DESCR('MQSeries client connection to server') +
	QMNAME(QM1)
	

You can also use the MQSeries Explorer utility on Windows to define these channels. The contents of the resulting binary channel definition table file represent the following details of the client connection:

Channel Name Channel Type Transport Type Connection Name Queue Manager
CHAN1 CLNTCONN TCP 10.40.60.68(1414) QM1

The client channel definition table file can be copied to the client machines to facilitate the connection to the server. Define the environment variables "MQCHLLIB" and "MQCHLTAB" on the client systems as:

MQCHLLIB : the directory where the channel definition table file is located
MQCHLTAB: Name of the channel definition table file

Note that the definition of MQSERVER environment variable overrides the definitions of MQCHLLIB and MQCHLTAB

The client program picks up the connection details from the channel definition table file during the ImqQueueManager::connect(). Remove the references to ImqChannel from the code and ensure that MQSERVER environment variable is NOT defined on your client system to enable the use of client channel definition table file.

You can define client connection channels with no queue manager name and the clients can connect to the queue managers associated with these channels by specifying "" (blank) or "*" as the queue manager name with the ImqQueueManager::connect() call. Clients can also specify a partial queue manager name using the wild card "*" in the name such as "QM*".

PHP5 class 学习笔记1:【上一篇】
typedef XXXXXXX:【下一篇】
【相关文章】
  • Interface and Abstract
  • apache22和resin3实现jsp功能
  • c++的构造
  • [原创]Linux环境汇编语言编程初步——使用C库函数
  • A good introduction to Peer-to-Peer!
  • c++ switch语句中的猫腻
  • c++程序员常用工具集
  • 浅析C++里面的宏。。。
  • Scott Meyers:C++史上最重要的五本书籍和五篇技术文章(ZT)
  • Linux上shmmax参数的设置及含义
  • 【随机文章】
  • struts学习总结
  • baidu分词算法分析之一
  • Run Shark with MySQL
  • bat example[1] ~
  • ASP中时间函数的使用(三)
  • proftpd+mod_sql+mod_quota安装手记
  • Word公式编辑器与MathType不能共存
  • isapi_ReWrite中文手册(局部)
  • 使用Flash基本工具绘制灯笼coming soon
  • 连接宽带错误678是什么意思?
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.