MQ C++API编程Word文档格式.docx
《MQ C++API编程Word文档格式.docx》由会员分享,可在线阅读,更多相关《MQ C++API编程Word文档格式.docx(15页珍藏版)》请在冰豆网上搜索。
如果实际的打开选项不符合在队列上进行操作的要求的话,那么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对象关联起来。
在打开分布列表之前,相关联的队列必须分配到队列名和包含队列的队列管理器,下面提供了一个打开分布列表的例子:
ImqDistributionListdlist;
ImqQueuequeueA,queueB;
ImqStringqueueManagerName(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关闭WebSphereMQ对象
WebSphereMQ对象在删除与其相应的ImqObject后即会自动关闭。
11.5.4断开与队列管理器的连接
当删除ImqQueueManager对象后,将隐式执行断开连接操作。
11.5.5消息放入队列
我们可以利用ImqQueue类的放置方法将消息放入ImqQueue或ImqDistributionList。
放置方法提供两种接口:
ImqBooleanput(ImqMessage&
msg);
msg,ImqPutMessageOptions&
pmo);
消息数据由ImqMessage类管理。
ImqMessage类继承自ImqMessageTracker类(它包括MQMD数据结构)和ImqCache类(它处理消息数据缓冲区)。
我们可以利用ImqMessageTracker类的setMessageId方法来设置消息身份。
ImqMessagemsg;
msg.setMessageId(msgId);
同样,我们也可以利用某些方法来访问关联性ID和组ID。
我们必须用ImqBinary类来创建messageId、correlationId和groupId。
该类包括用于MQI的BYTExx数据类型,它提供某些进行基本操作的方法。
下例显示了如何利用ImqBinary来创建二进制对象。
ImqBinarycorrelationId;
MQBYTE24byteId=“BYTEID1234”;
correlationId.set(byteId,sizeof(byteId));
准备消息数据
该API与MQIAPI的不同之处在于准备和处理消息数据的方法不同。
在MQI中,从分配正确的缓冲区到储存数据,再到读取消息时处理消息中不同的可能标题,消息完全由应用程序管理。
在C++API中,添加了一些缓冲功能,而且缓冲区由ImqCache对象管理。
缓冲区通过继承与每个消息(ImqMessage对象)相关联。
默认情况下,缓冲区由ImqCache自动提供,或者也可以由应用程序利用以下任何一种ImqCache对象方法来提供:
useEmptyBuffer:
这种方法允许应用程序分配一个固定长度的空白缓冲区给ImqMesage对象。
如果没有分配实际消息长度的话,那么会将消息长度自动设置为零,而且缓冲区也将是空的。
charpszBuffer[24]=“HelloWorld”;
msg.useEmptyBuffer(pszBuffer,sizeof(pszBuffer));
msg.setFormat(MQFMT_STRING);
msg.setMessageLength(12);
或
charpszBuffer[12];
useFullBuffer:
这种方法允许应用程序分配一个已经准备好的消息缓冲区给ImqMessage对象。
该缓冲区将不是空的,消息长度也将被设为方法调用所提供的长度。
charpszBuffer[]=“Helloworld”;
msg.useFullBuffer(pszBuffer,sizeof(pszBuffer));
消息缓冲区可以重复使用,我们也可以利用ImqCache类的setMessegeLength方法来设置消息长度,因此发送字节的数量也各不相同。
由应用程序提供消息缓冲区的优势在于无需进行数据拷贝,因为数据可以直接在缓冲区中准备。
为了将ImqCache再设为自动的缓冲区,应用程序可以用空缓冲区指针和零(0)长度调用useEmptyBuffer。
当自动提供缓冲区时,缓冲区随着消息的增长而增长。
这为准备消息前却不知道消息长度提供了更多的灵活性。
可以利用ImqCache写入方法将消息(数据)拷贝到缓冲区中。
msg.write(12,“Helloworld”);
我们可以利用ImqMessage的writeItem方法将项目拷贝到缓冲区中。
比方说,您可能希望向消息添加一个死信标题,并将其放入死信队列中。
下例显示了如何创建一个ImqDeadLetterHeader并将其插入现有消息的开始部分。
ImqDeadLetterHeaderheader;
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类的提交或回滚方法来结束它。
ImqPutMessageOptionspmo;
pmo.setSyncPointParticipation(TRUE);
pqueue.put(msg,pmo);
如欲了解ImqQueue类可用选项的更多信息,请参见《UsingC++》手册。
11.5.6从队列获取消息
我们可以利用该类提供的获取方法从ImqQueue对象上获取消息。
ImqQueue获取方法提供四种接口:
ImqBooleanget(ImqMessage&
msg,ImqGetMessageOptions&
options);
options,
constsize_tbuffer-size);
msg,constsize_tbuffer-size);
在方法调用之后,消息信息会包含在ImqMessage对象中。
缺省情况下,消息缓冲区由系统提供,可以利用dataPointer或bufferPointer方法获得。
消息数据长度可以利用ImqCache类的dataLength方法获得。
pqueue.get(msg);
char*pszDataPointer=msg.dataPointer();
intiDataLength=msg.dataLength();
注意:
在每次获取方法调用之后,数据缓冲区的物理位置可能发生改变,因此我们建议不要使用实际的缓冲区指针来访问数据。
我们应当利用dataPointer或bufferPointer方法来重新分配数据指针。
如果应用程序希望提供固定长度的缓冲区来接收消息数据的话,那么我们可以在利用ImqQueue的获取方法前使用ImqCache的useEmptyBuffer方法。
给定缓冲区的长度将限制消息长度,因此在应用程序设计中必须考虑到长消息的情况。
charpszBuffer[BUFFER_LENGTH];
pqueue.useEmptyBuffer(pszBuffer,BUFFER_LENGTH);
在这种情况下,我们可以一直使用实际的缓冲区指针pszBuffer,但是我们还是建议采用dataPointer方法以保证可移植性。
读取消息数据
一旦接收到消息,那么根据消息格式,消息数据可能是项目形式的,也可能是原始的用户数据形式。
但项目必须是分别连续处理的数据的各个部分。
我们可以利用ImqMessage的formatIs来确保消息格式的有效性。
如果消息格式代表着任何已知消息标题数据结构,那么我们可以利用ImqMessage的readItem方法从消息中获得结构。
该API具有三个实现定义的消息标题:
死信标题(ImqDeadLetterHeaderclass);
IMS桥标题(ImqIMSBridgeHeader);
参照标题(ImqReferenceHeader)。
每个标题都对应于一个WebSphereMQ定义的消息格式。
用户可以指定ImqItem类来定义其他类型的格式。
if(msg.formatIs(MQFMT_DEAD_LETTER_HEADER)){
/*ThereadItemmethodmustbecalledwiththerightclassofobjectpointer*/
if(msg.readItem(header)){
/*Performthecorrespondingoperationforthisitemtype*/
}
}
如果消息格式未知的话,那么正如前面所讲解过的那样,我们可以利用dataPointer方法来直接访问消息数据。
更多的获取方法选项
ImqGetMessageOptions类为消息接收过程提供了更多信息,如:
获取操作的等待间隔;
匹配选项;
消息选项;
同步点参加;
组状态;
细分状态。
我们可以利用ImqGetMessageOptions的setOptions方法来指定任何MQI中可用的消息获取选项。
其中MQGMO_WAIT选项应用较多,它为要完成的获取操作提供了一个等待间隔。
这样,如果期待的消息还未到达队列的话,那么获取方法在返回错误前会等待一定的时间,时间长度是用ImqGetMessageOptions类的setWaitInterval方法来指定。
下例显示了如何用无限等待选项从队列获取消息。
ImqGetMessageOptionsgmo;
gmo.setOptions(MQGMO_WAIT);
/*Setthewaitintervaltounlimitedmeaningthatthegetoperation*/
/*willwaituntilonemessageappearsinthequeue.*/
gmo.setWaitInterval(MQWI_UNLIMITED);
pqueue.get(msg,gmo);
从队列获取特定消息
通过ImqMessageTracker类中的消息属性的任意结合,我们可以确认特定的消息。
MessageId
CorrelationId
GroupId
这些选项必须在获取方法调用中传递的ImqMessage对象中指定。
ImqGetMessageOptions类为应用程序提供了一种在指定消息查找过程中将使用什么选项的方法。
gmo.setMatchOptions(MQMO_MATCH_MSG_ID);
If(pqueue.get(msg,gmo)){
/*Performanyoperationwiththismessage*/
如果一个以上的消息与给定标准相匹配,那么将返回这些消息中的第一个,并且获取方法的后续调用将提供所有消息的访问。
如果找到了匹配的消息,消息对象信息在获取方法调用后将发生改变,否则函数会返回假。
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);
/*Browsingallthemessagesinthequeueinsequentialorder*/
while(pqueue.get(msg,gmo)){
/*Performsomeoperationwiththemessage*/
...
/*TheMessageIdandCorrelationIdmustbesettonullbeforethenextgetmethodcall*/
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,较之于采用MQIAPI时的情况,查询并设定对象属性实在是相当直接的操作。
这里,ImqObject类提供了两种查询方法,可查询任何显示的整数或字符属性。
ImqBooleaninquire(constMQLONGint-attr,MQLONG&
value);
ImqBooleaninquire(constMQLONGchar-attr,char*&
buffer,constsize_tlength);
int-attr和char-attr参数将MQIA_*和MQCA_*指数赋予属性。
整数对象属性值在值参数中返回,正如下面这段代码所显示的那样:
MQLONGdepth;
pqueue.inquire(MQIA_CURRENT_Q_DEPTH,depth);
printf(“Thecurrentqueuedepthis:
%d“,depth);
字符对象属性值在缓冲区参数中返回,正如下面这段代码所显示的那样:
charqname[MQCA_Q_MGR_NAME_LENGTH];
pqueue.inquire(MQCA_Q_MGR_NAME,qname,MQCA_Q_MGR_NAME_LENGTH);
%s“,qname);
缓冲区必须足够大,以致于可以容纳属性值。
缓冲区的长度必须在长度参数中指定。
设置对象属性为了设置队列属性,ImqObject提供了两种查询属性的方法。
ImqBooleanset(constMQLONGint-attr,MQLONG&
value);
ImqBooleanset(constMQLONGchar-attr,char*buffer,constsize_tlength);
下面这段代码显示了这些函数可能的用法:
/*Thisinstructioninhibitsanyputoperationonanytypeofqueue.*/
pqueue.set(MQIA_INHIBIT_PUT,MQQA_PUT_INHIBITED);
/*Thisinstructioninhibitsanygetoperationonanylocalqueue.*/
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