ibmMQ-第十一章

第十一章 用 C++ API编程
目标
1.	了解WebSphere MQ C++ API。该API 是MQI API 的面向对象的延伸。
2.	学习这种API 的基本概念、体系结构模型,以及API 可用性。
3.	介绍利用这种API 所能进行的一些基本操作。
4.最后,我们将探讨如何利用该API 的编程模式。
11.1 概述
WebSphere MQ C++接口是MQI API的延伸。就WebSphere MQ 消息发布接口而言,为程序员提供了一种面向对象的方法。由于该API 是以面向对象的模型为基础的,属性和方法都继承到子类中。在下面各节中,我们将确定作为父类的方法。

关键特性:
C++ MQI 可提供MQI API 的所有特性,如获取、放置及浏览消息等,其还允许用户查询并设置对象选项。此外,还可提供以下特性:
	WebSphere MQ 数据结构的自动初始化;
	及时的队列管理器连接和队列打开;
	隐式队列关闭和队列管理器断开;
	死信标题发送和接收;
	IMS 桥标题发送和接收;
	参照消息标题发送和接收;
	触发器消息接收;
	CICS 桥标题发送和接收;
	工作标题发送和接收;
	客户机渠道定义。
11.2 平台和语言
WebSphere MQ C++允许您使用C++语言编写WebSphere MQ应用程序,WebSphere MQ C++可以在下列服务器平台使用:
•	WebSphere MQ for AIX, Version 5.3 
•	WebSphere MQ for HP-UX, Version 5.3 
•	WebSphere MQ for iSeries, Version 5.3 
•	WebSphere MQ for Linux for Intel, Version 5.3 
•	WebSphere MQ for Linux for zSeries, Version 5.3 
•	WebSphere MQ for Solaris, Version 5.3 
•	WebSphere MQ for Windows, Version 5.3 
•	WebSphere MQ for z/OS, Version 5.3 
•	WebSphere MQ for Compaq Tru64 UNIX, Version 5.1 
•	WebSphere MQ for OS/2 Warp, Version 5.1 
•	WebSphere MQ for Sun Solaris, Intel Platform Edition, Version 5.1 
同时也适用于以下客户机环境:
•	AIX 
•	Compaq Tru64 UNIX 
•	HP-UX 
•	Linux for Intel 
•	Linux for zSeries 
•	OS/2 
•	Solaris (SPARC and Intel Platform Editions) 
•	Windows 3.1 
•	Windows 95 
•	Windows NT(R) 
•	Windows 2000 

11.3库
下表显示了在各个可用平台上使用该API 开发的C++程序进行编译时所需的库。
平台	库
WebSphere MQ for Windows NT	IMQ*.LIB
WebSphere MQ for AIX	In a non-threaded application:
libimq*.a
In a threaded application:
libimq*_r.a
WebSphere MQ for Sun Solaris	imq*.so
WebSphere MQ for HP-UX	imq*.so

imqi.hpp 标题包含所有利用此API 所需的声明。

11.4体系结构模型
此API 中所有的类均继承于ImqError 类,其允许错误条件下(error condition)与每个对象相关。如下图( 队列管理类)。
 
图,队列管理类
上图显示了与项目有关的类(item-related classes),这些类包含MQI提供的消息标题结构(如IMS 桥标题和死信标题)。


 
图,项目处理类

队列管理类和项目处理类都利用以下类和数据类型:
ImqBinary 类,包括字节数组(如MQBYTE24);
ImqBoolean 数据类型,可定义为typedef unsigned char ImqBoolean;
ImqString 类,包含字符数组(如MQCHAR64)。
我们将就其与MQI API 特性的关系来阐述该API 体系结构的特性。可将所有的MQI 数据结构实体归入合适的对象类中,从而使我们可就不同的数据结构字段采用不同的方法。有句柄的实体(继承于ImqObject 类或其派生物之一)可向我们提供MQI 的抽象界面。此外,这些对象具有智能行为,与过程MQI 实施相比,能减少方法调用量。举例来说,到队列管理器的连接根据需要被创建或删除。ImqMessage 类包括MQMD 数据结构,提供缓冲功能,可以作为用户数据和项目的保存点。缓冲区可以由应用程序提供,也可以由系统自动创建。ImqItem 类代表着消息主题中的项目。项目是指需要连续且分别进行处理的消息的各个部分。除了常规用户信息外,项目还可能是死信标题或触发器消息。每个项目都有对象类,与一种可辨认的WebSphere MQ 消息格式相对应。用户数据没有对象类,但是可以特别指明ImqItem,从而将其写入。如果不写入的话,那么用户数据处理则交由应用程序来完成。ImqChannel 类包括渠道定义(MQCD)结构,使得我们可以确定在客户机环境中执行ImqQueueManager::connect()时要用到的连接选项。欲了解有关WebSphere MQ 自动通道定义选项的更多信息,请参见《WebSphere MQ Intercommunication》。
11.5用C++ API编程
现在,我们将阐述如何利用上述API 来实现基本的WebSphere MQ 操作,如连接到队列管理器、打开一个队列或发送/接收消息。
11.5.1连接到队列管理器
为了连接到队列管理器,我们将使用ImqQueueManager 类(它包括WebSphere MQ 队列管理器对象)。队列管理器名可以由构造器调用提供,也可以用ImqQueueManager 类的setName 方法来提供。
ImqQueueManager qmanager;
qmanager.setName(name);
或者
ImqQueueManager *pmanager = new ImqQueueManager(name);
提示:我们在本章其余部分中都将用到qmanager 对象。而后,我们可以利用ImqQueueManager 的连接方法来建立连接。
qmanager.connect();
队列管理器的信息可以利用ImqQueueManager类来访问。

11.5.2打开WebSphere MQ对象
我们可以根据对象是队列还是其他类型的对象,然后利用ImqObject 或ImqQueue 类来打开WebSphere MQ 对象。一般来说,我们都会使用ImqQueue 类,除非必须要查询或设定某些对象属性。

	打开队列
ImqQueue 类包括WebSphere MQ 队列对象,并向队列对象行为添加了某些信息。在可以对队列进行任何放置或获取操作前, 必须利用ImqQueue 类的setConnectionReference 方法将包含队列的队列管理器分配给ImqQueue 对象。
ImqQueue pqueue;
pqueue.setConnectionReference(pmanager);

可在对象构建过程中提供队列名,也可以利用ImqObject 类的setName 方法提供队列名。
pqueue.setName(queuename);
当发出放置或获取调用时,将自动采用要求的选项打开队列,也就是说,不需要进行显式打开操作。如果实际的打开选项不符合在队列上进行操作的要求的话,那么ImqQueue对象就会关闭并重新打开队列。
在某些情况下,根据被打开队列的类型,将会导致一些额外的开销或某些问题。为了避免自动关闭和重新打开队列,我们必须利用ImqObject 类的openFor 方法或setOpenOptions 直接设置打开选项。我们也可以利用ImqObject 类的打开方法显式打开队列,但是如果打开选项已经指定的话,那么较之于这种接口提供的隐式打开,它并不能提供什么重大优势。
pqueue.setOpenOptions(MQOO_OUTPUT | MQOO_INPUT_SHARED);
或者
pqueue.openFor(MQOO_OUTPUT | MQOO_INPUT_SHARED);
openFor 方法不断添加指定的打开选项到实际分配给对象的选项。ImqQueue 对象的默认打开选项是MQOO_INQUIRE。
	打开动态队列
动态队列不能通过重新打开方式自动关闭,因为对动态队列进行关闭操作会删除该队列。因此,打开动态队列时,我们必须指定打开选项。
队列模型的名由ImqObject 类的setName 方法指定,动态队列名或其前缀可以用ImqQueue 类的setDynamicQueueName 方法确定。动态队列的实际名可以在队列打开后用dynamicQueueName 方法获得。
pqueue.setDynamicQueueName(dynamicqueuename);

	打开分布列表
分布列表由ImqDistributionList 类进行管理,它继承自ImqQueue 类。可以利用ImqQueue 类的setDistributionReference 方法将任意数量的ImqQueue 对象和一个ImqDistributionList 对象关联起来。

在打开分布列表之前,相关联的队列必须分配到队列名和包含队列的队列管理器,下面提供了一个打开分布列表的例子:
ImqDistributionList dlist;
ImqQueue queueA, queueB;
ImqString queueManagerName(pmanager.name());
queueA.setConnectionReference(pmanager);
queueB.setConnectionReference(pmanager);
queueA.setName(queuename1);
queueB.setName(queuename2);
queueA.setQueueManagerName( queueManagerName);
queueB.setQueueManagerName( queueManagerName);
queueA.setDistributionListReference(dlist);
queueB.setDistributionListReference(dlist);


一旦设置好分布列表的队列,就可以向其他任何ImqQueue 对象一样来打开分布列表并对其进行操作。
11.5.3 关闭WebSphere MQ对象
WebSphere MQ 对象在删除与其相应的ImqObject 后即会自动关闭。
11.5.4 断开与队列管理器的连接
当删除ImqQueueManager 对象后,将隐式执行断开连接操作。
11.5.5 消息放入队列
我们可以利用ImqQueue 类的放置方法将消息放入ImqQueue 或ImqDistributionList。放置方法提供两种接口:
ImqBoolean put(ImqMessage & msg);
ImqBoolean put(ImqMessage & msg, ImqPutMessageOptions & pmo);

消息数据由ImqMessage 类管理。ImqMessage 类继承自ImqMessageTracker 类(它包括MQMD 数据结构)和ImqCache 类(它处理消息数据缓冲区)。

我们可以利用ImqMessageTracker 类的setMessageId 方法来设置消息身份。
ImqMessage msg;
msg.setMessageId(msgId);

同样,我们也可以利用某些方法来访问关联性ID 和组ID。我们必须用ImqBinary 类来创建messageId、correlationId 和groupId。该类包括用于MQI的BYTExx 数据类型,它提供某些进行基本操作的方法。下例显示了如何利用ImqBinary 来创建二进制对象。

ImqBinary correlationId ;
MQBYTE24 byteId =“BYTEID1234”;
correlationId.set(byteId,sizeof(byteId ));

准备消息数据
该API 与MQI API 的不同之处在于准备和处理消息数据的方法不同。在MQI 中,从分配正确的缓冲区到储存数据,再到读取消息时处理消息中不同的可能标题,消息完全由应用程序管理。
在C++ API 中,添加了一些缓冲功能,而且缓冲区由ImqCache 对象管理。缓冲区通过继承与每个消息(ImqMessage 对象)相关联。默认情况下,缓冲区由ImqCache 自动提供,或者也可以由应用程序利用以下任何一种ImqCache 对象方法来提供:
useEmptyBuffer:这种方法允许应用程序分配一个固定长度的空白缓冲区给ImqMesage 对象。如果没有分配实际消息长度的话,那么会将消息长度自动设置为零,而且缓冲区也将是空的。
ImqMessage msg;
char pszBuffer[24]=“Hello World”;
msg.useEmptyBuffer(pszBuffer, sizeof(pszBuffer));
msg.setFormat(MQFMT_STRING);
msg.setMessageLength(12);
或
char pszBuffer[12];
msg.useEmptyBuffer(pszBuffer, sizeof(pszBuffer));
msg.setFormat(MQFMT_STRING);
useFullBuffer:这种方法允许应用程序分配一个已经准备好的消息缓冲区给ImqMessage 对象。该缓冲区将不是空的,消息长度也将被设为方法调用所提供的长度。
ImqMessage msg;
char pszBuffer[] =“Hello world”;
msg.useFullBuffer(pszBuffer, sizeof(pszBuffer));
msg.setFormat(MQFMT_STRING);
消息缓冲区可以重复使用,我们也可以利用ImqCache 类的setMessegeLength 方法来设置消息长度,因此发送字节的数量也各不相同。由应用程序提供消息缓冲区的优势在于无需进行数据拷贝,因为数据可以直接在缓冲区中准备。
为了将ImqCache 再设为自动的缓冲区,应用程序可以用空缓冲区指针和零(0)长度调用useEmptyBuffer。当自动提供缓冲区时,缓冲区随着消息的增长而增长。这为准备消息前却不知道消息长度提供了更多的灵活性。可以利用ImqCache 写入方法将消息(数据)拷贝到缓冲区中。
msg.write(12, “Hello world”);
我们可以利用ImqMessage 的writeItem 方法将项目拷贝到缓冲区中。比方说,您可能希望向消息添加一个死信标题,并将其放入死信队列中。
下例显示了如何创建一个ImqDeadLetterHeader 并将其插入现有消息的开始部分。
ImqDeadLetterHeader header;
header.setDestinationQueueManagerName(pmanager.name());
header.setDestinationQueueName(pqueue.name());
header.setPutApplicationName(/*?*/);
header.setPutApplicationType(/*?*/);
header.setPutDate(/* TODAY*/);
header.setPutTime(/* NOW*/);
header.setDeadLetterReasonCode(/* REASON*/);
msg.writeItem(header);
可以在放置方法中使用更多选项,正如ImqQueue 类的放置方法提供了两种接口。在将消息放到队列上时,必须经常指定更多的选项。我们可以用以ImqPutMessageOptions对象为形式的第二个参数调用放置方法来指定这些选项。ImqPutMessageOptions 类包括MQPMO 数据结构,它允许应用程序指定更多的选项,如同步点控制或消息上下文。
下例显示了如何启动并设置同步点选项。这将启动本地队列管理器事务处理,我们可以利用ImqQueueManager 类的提交或回滚方法来结束它。
ImqQueue pqueue;
ImqMessage msg;
ImqPutMessageOptions pmo;

pmo.setSyncPointParticipation(TRUE);
pqueue.put(msg, pmo);

如欲了解ImqQueue 类可用选项的更多信息,请参见《Using C++》手册。
11.5.6从队列获取消息
我们可以利用该类提供的获取方法从ImqQueue 对象上获取消息。ImqQueue 获取方法提供四种接口:
ImqBoolean get(ImqMessage & msg, ImqGetMessageOptions & options);
ImqBoolean get(ImqMessage & msg);
ImqBoolean get(ImqMessage & msg, ImqGetMessageOptions & options,
const size_t buffer-size);
ImqBoolean get(ImqMessage & msg, const size_t buffer-size);

在方法调用之后,消息信息会包含在ImqMessage 对象中。缺省情况下,消息缓冲区由系统提供,可以利用dataPointer 或bufferPointer 方法获得。消息数据长度可以利用ImqCache 类的dataLength 方法获得。
pqueue.get(msg);
char *pszDataPointer = msg.dataPointer();
int iDataLength = msg.dataLength(); 
注意:
在每次获取方法调用之后,数据缓冲区的物理位置可能发生改变,因此我们建议不要使用实际的缓冲区指针来访问数据。我们应当利用dataPointer 或bufferPointer 方法来重新分配数据指针。
如果应用程序希望提供固定长度的缓冲区来接收消息数据的话,那么我们可以在利用ImqQueue 的获取方法前使用ImqCache 的useEmptyBuffer 方法。给定缓冲区的长度将限制消息长度,因此在应用程序设计中必须考虑到长消息的情况。

char pszBuffer[BUFFER_LENGTH];
pqueue.useEmptyBuffer(pszBuffer, BUFFER_LENGTH);
pqueue.get(msg);

在这种情况下,我们可以一直使用实际的缓冲区指针pszBuffer,但是我们还是建议采用dataPointer 方法以保证可移植性。

读取消息数据
一旦接收到消息,那么根据消息格式,消息数据可能是项目形式的,也可能是原始的用户数据形式。但项目必须是分别连续处理的数据的各个部分。我们可以利用ImqMessage 的formatIs 来确保消息格式的有效性。如果消息格式代表着任何已知消息标题数据结构,那么我们可以利用ImqMessage 的readItem 方法从消息中获得结构。该API 具有三个实现定义的消息标题:
死信标题(ImqDeadLetterHeader class);
IMS 桥标题(ImqIMSBridgeHeader);
参照标题(ImqReferenceHeader)。

每个标题都对应于一个WebSphere MQ定义的消息格式。用户可以指定ImqItem 类来定义其他类型的格式。

if (msg.formatIs(MQFMT_DEAD_LETTER_HEADER)) {
ImqDeadLetterHeader header;
/*The readItem method must be called with the right class of object pointer*/
if (msg.readItem(header)) {
/*Perform the corresponding operation for this item type*/
} 
}

如果消息格式未知的话,那么正如前面所讲解过的那样,我们可以利用dataPointer 方法来直接访问消息数据。

更多的获取方法选项
ImqGetMessageOptions 类为消息接收过程提供了更多信息,如:
获取操作的等待间隔;
匹配选项;
消息选项;
同步点参加;
组状态;
细分状态。

我们可以利用ImqGetMessageOptions 的setOptions 方法来指定任何MQI 中可用的消息获取选项。其中MQGMO_WAIT 选项应用较多,它为要完成的获取操作提供了一个等待间隔。这样,如果期待的消息还未到达队列的话,那么获取方法在返回错误前会等待一定的时间,时间长度是用ImqGetMessageOptions 类的setWaitInterval 方法来指定。

下例显示了如何用无限等待选项从队列获取消息。
ImqGetMessageOptions gmo;
ImqMessage msg;
gmo.setOptions(MQGMO_WAIT);
/*Set the wait interval to unlimited meaning that the get operation*/
/*will wait until one message appears in the queue.*/
gmo.setWaitInterval(MQWI_UNLIMITED);
pqueue.get(msg,gmo);

从队列获取特定消息
通过ImqMessageTracker 类中的消息属性的任意结合,我们可以确认特定的消息。
MessageId
CorrelationId
GroupId
这些选项必须在获取方法调用中传递的ImqMessage 对象中指定。ImqGetMessageOptions 类为应用程序提供了一种在指定消息查找过程中将使用什么选项的方法。

gmo.setMatchOptions(MQMO_MATCH_MSG_ID);
msg.setMessageId(msgId);
If (pqueue.get(msg,gmo)) {
/*Perform any operation with this message*/
}

如果一个以上的消息与给定标准相匹配,那么将返回这些消息中的第一个,并且获取方法的后续调用将提供所有消息的访问。如果找到了匹配的消息,消息对象信息在获取方法调用后将发生改变,否则函数会返回假。

11.5.7浏览队列上的消息
我们可以利用ImqQueue 获取方法浏览队列上的消息。必须用MQOO_BROWSE 选项来打开ImqQueue 对象。我们可以用setOpenOptions 或openFor 方法来实现这一目的。

pqueue.setOpenOptions(MQOO_BROWSE);
或者
pqueue.openFor(MQOO_BROWSE);

在队列对象已被打开并用于浏览后,我们必须用以下选项调用ImqQueue 获取方法:MQGMO_BROWSE_FIRST 消息选项,如果您希望浏览光标位于符合ImqMessage 对象指定的标准的第一个消息处的话;MQGMO_BROWSE_NEXT 消息选项,如果您希望浏览光标移动到符合ImqMessage 对象指定的标准的下一个消息的话。
获取方法将返回ImqMessage 对象的更新版本,浏览光标也将指向当前消息的信息,并且当前消息不会从队列中删除。队列对象一旦打开, 浏览光标就会指向队列中的第一个消息, 因此MQGMO_BROWSE_NEXT 选项与MQGMO_BROWSE_FIRST 具有相同的行为。

gmo.setOptions(MQGMO_BROWSE_NEXT | MQGMO_WAIT);
/*Browsing all the messages in the queue in sequential order*/
while (pqueue.get(msg,gmo)) {
/*Perform some operation with the message*/
...
      /*The MessageId and CorrelationId must be set to null before the next get method call*/
msg.setMessageId(MQMI_NONE);
msg.setCorrelId(MQCI_NONE);
}

可以按照物理顺序或逻辑顺序来浏览消息。
根据队列的消息到达顺序(MsgDeliverySequence),物理排序可以是FIFO(先进/先出)排序或优先级内FIFO 排序。逻辑顺序就是说,即便另一个组中的任何消息在本组最后一条消息接收前出现,属于同一个组的消息仍将按照其在队列中的正确位置顺序排列。为了浏览逻辑顺序的消息,我们在调用方法时必须指定MQGMO_LOGICAL_ORDER 选项。

gmo.setOptions(MQGMO_BROWSE_NEXT | MQGMO_WAIT | 
MQGMO_LOGICAL_ORDER);
11.5.8查询并设置对象属性
	查询属性
利用此种API,较之于采用MQI API 时的情况,查询并设定对象属性实在是相当直接的操作。这里,ImqObject 类提供了两种查询方法,可查询任何显示的整数或字符属性。

ImqBoolean inquire(const MQLONG int-attr, MQLONG & value );
ImqBoolean inquire(const MQLONG char-attr, char * & buffer, const size_t length);

int-attr 和char-attr 参数将MQIA_*和MQCA_*指数赋予属性。整数对象属性值在值参数中返回,正如下面这段代码所显示的那样:

MQLONG depth;
pqueue.inquire(MQIA_CURRENT_Q_DEPTH, depth);
printf(“The current queue depth is: %d“,depth);

字符对象属性值在缓冲区参数中返回,正如下面这段代码所显示的那样:

char qname[MQCA_Q_MGR_NAME_LENGTH];
pqueue.inquire(MQCA_Q_MGR_NAME, qname, MQCA_Q_MGR_NAME_LENGTH);
printf(“The current queue depth is: %s“,qname);

缓冲区必须足够大,以致于可以容纳属性值。缓冲区的长度必须在长度参数中指定。设置对象属性为了设置队列属性,ImqObject 提供了两种查询属性的方法。
ImqBoolean set(const MQLONG int-attr, MQLONG & value);
ImqBoolean set(const MQLONG char-attr, char * buffer, const size_t length);

下面这段代码显示了这些函数可能的用法:
/*This instruction inhibits any put operation on any type of queue. */
pqueue.set(MQIA_INHIBIT_PUT,MQQA_PUT_INHIBITED);

或者
/*This instruction inhibits any get operation on any local queue.*/
pqueue.set(MQIA_INHIBIT_GET,MQQA_GET_INHIBITED);

只有下面这些队列属性值可以利用上述函数进行调整:

- MQIA_INHIBIT_PUT
- MQCA_TRIGGER_DATA
- MQIA_DIST_LISTS
- MQIA_INHIBIT_GET
- MQIA_TRIGGER_CONTROL
- MQIA_TRIGGER_DEPTH
- MQIA_TRIGGER_MSG_PRIORITY
- MQIA_TRIGGER_TYPE
- MQIA_DIST_LISTS
- MQIA_INHIBIT_GET
11.5.9事务处理管理
本地资源管理器事务处理可以通过在ImqPutMessage 或ImqGetMessage 选项类中设置同步点参加来启动。

ImqPutMessageOptions pmo;
/*This starts a local resource manager transaction*/
pmo.setSyncPointParticipation(TRUE);
pqueue.put(msg,pmo);

或者

ImqGetMessageOptions gmo;
/*This starts a local resource manager transaction*/
gmo.setSyncPointParticipation(TRUE);
pqueue.get(msg,gmo);

ImqQueueManager 对象提供了用此API 开始、提交或取消分布式事务处理所需的事务处理管理接口。分布式事务处理由ImqQueueManager 开始方法调用来启动。一个事务处理开始和结束调用中的任何操作都是事务处理的一部分。

/*This call starts a distributed transaction*/
pmanager.begin();

只有在不存在其他本地或分布式事务处理管理的情况下,才能启动分布式事务处理管理。如果事务处理成功的话,本地和分布式事务处理管理都可以由ImqQueueManager 提交方法调用来终止。它们也可以由ImqQueueManager 取消方法调用来终止。

pmanager.commit();
或者
pmanager.backout();
11.5.10消息分组
我们可以利用ImqMessageTracker 的setGroupId 方法将消息分组。我们也必须利用ImqMessage 的setMessageFlags 方法给出MQMF_MSG_IN_GROUP 或MQMF_LAST_MSG_IN_GROUP 标记,从而确认组中的消息。
MQI API的例子显示了如何将三条消息作为一个组进行发送。前两条消息将用MQMF_MSG_IN_GROUP 标记发送, 而第三条消息则将利用MQMF_LAST_MSG_IN_GROUP 发送。下例显示了消息分组。

/*Setting put message options and message descriptor versions*/
BYTE24 MY_GROUP_ID = “123456”;
ImqPutMessageOptions pmo;
ImqMessage message;
ImqBinary grpId;

/*Set the grpId binary object value*/
grpId.set(MY_GROUP_ID,sizeof(MY_GROUP_ID);

/*Sets the put message options to generate a new message ID for every message put into the queue and to put the messages in their logical order into the queue*/
pmo.setOptions(MQPMO_LOGICAL_ORDER | MQPMO_NEW_MSG_ID);
message.setMessageFlags(MQMF_MSG_IN_GROUP);

/*Assign the GroupId*/
message.setGroupId(grpId);

/*Puts a first message of the group*/
message.write(“First messsage”);
pqueue.put(message,pmo);

/*Puts a second message of the group*/
message.write(“Middle messsage”);
pqueue.put(message,pmo);

/*Puts the final message of the group. The final message must be identified by giving the MQMF_LAST_MSG_IN_GROUP flags in the message descriptor structure*/
message.setMessageFlags(MQMF_LAST_MSG_IN_GROUP);
message.write(“Last messsage”);
pqueue.put(message,pmo);

而后, 我们可以利用ImqGetMessageOptions 类setOptions 方法中的MQGMO_LOGICAL_ORDER 选项,并以这些消息在队列中的逻辑循序接收它们。

ImqPutMessageOptions pmo;
ImqMessage message;
char buffer[101];
message.setEmptyBuffer(buffer, sizeof(buffer)-1);

gmo.setOptions(MQGMO_LOGICAL_ORDER + MQGMO_WAIT + MQGMO_CONVERT);

/* 15 second limit for waiting */
gmo.setWaitInterval(1500); 

gmo.setMatchOptions(MQGMO_NONE);
while (pqueue.completionCode() != MQCC_FAILED) {
md.setEncoding(MQENC_NATIVE);
md.setCharacterSet(MQCCSI_Q_MGR);
if (pqueue.get(message)) {
buffer[message.dataLength] = 0;
printf("message <%s>\n", buffer);
/* report reason, if any*/
if (queue.reasonCode() != MQRC_NONE) {
printf("MQGET ended with reason code %ld\n", Reason);
} else {
if (queue.reasonCode() == MQRC_NO_MSG_AVAILABLE) {
printf("no more messages\n");
} 
} 
}

另外,队列管理器可以控制是否完全接收消息组。如果我们仅希望队列中出现完整的消息组的话, 那么我们可以在ImqGetMessageOptions 的setOptions 方法中设置MQGMO_ALL_MSGS_AVAILABLE 等选项。
11.6本章小结
本章已经讨论WebSphere MQ C++ API。该API 是MQI API 的面向对象的延伸。此外我们还讨论这种API 的基本概念、体系结构模型,以及API 可用性。而后,我们介绍了利用这种API 所能进行的一些基本操作,如:
	连接到队列管理器并断开与队列管理器的连接;
	打开及关闭WebSphere MQ 对象(如队列对象);
	向队列发送消息并从队列获取消息;
	事务处理管理;
	消息分组。
最后,我们探讨了如何利用该API 的编程模式。
11.7本章练习
1.	使用WebSphere MQ C++ API 编写文件的发送程序。
2.	使用WebSphere MQ C++ API编写文件的接收程序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值