无效的MQ标头结构

时间:2018-03-21 06:12:49

标签: c ibm-mq

我正在尝试使用MQPUT函数在队列中放入带有RFH2标头的消息。所述函数返回完成代码2和原因2142,根据IBM docs意味着头结构无效。此link上的文档指定了需要检查的字段。标题和消息描述符包含以下内容:

MQMD:
StrucId          = 'MD  '
Version          = 2
Report           = 0
MsgType          = 8
Expiry           = -1
Feedback         = 0
Encoding         = 273
CodedCharSetId   = 1208
Format           = 'MQHRF2  '
Priority         = -1
Persistence      = 2
MsgId            = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
CorrelId         = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
BackoutCount     = 0
ReplyToQ         = ''
ReplyToQMgr      = ''
UserIdentifier   = ''
AccountingToken  = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ApplIdentityData = ''
PutApplType      = 0
PutApplName      = ''
PutDate          = ''
PutTime          = ''
ApplOriginData   = ''
GroupId          = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
MsgSeqNumber     = 1
Offset           = 0
MsgFlags         = 0
OriginalLength   = -1

MQRFH2:
StrucId        = 'RFH '
Version        = 2
StrucLength    = 128
Encoding       = 273
CodedCharSetId = 0
Format         = 'MQSTR   '
Flags          = 0
NameValueCCSID = 1208

我无法理解标头是如何无效的,我该如何解决这个问题。 提前谢谢。

int SendMessage(PMQHCONN connectionDescriptorPtr, PMQHOBJ queueDescriptorPtr, const char* payload, const char* message)
{
  MQLONG completionResult;
  MQLONG reason;

  unsigned char* buffer = NULL;

  PMQRFH2 pHeader;

  PMQINT32 pNameValueLength;

  PMQCHAR pNameValueData;

  PMQCHAR pMessage;

  PMQCHAR p;

  MQLONG bufferLength;
  MQLONG structLength;
  MQLONG nameValueLength;

  size_t payloadLength = strlen(payload);
  size_t messageLength = strlen(message);
  size_t sizeOfLength = sizeof(MQINT32);
  size_t headerStructLength = MQRFH_STRUC_LENGTH_FIXED_2;
  size_t padding = CalcPadding(payload);
  size_t i;

  /* mqmd */
  MQMD md = {MQMD_DEFAULT};

  MQPMO pmo = {MQPMO_DEFAULT};

  structLength = (MQLONG) (headerStructLength + sizeOfLength + payloadLength + padding);

  /* calc total buffer length */
  bufferLength = (MQLONG) (headerStructLength + sizeOfLength + payloadLength + padding + messageLength);
  printf("Lengths:\n"
         "  Header:\n"
         "     structure    : %zu\n"
         "     length field : %zu\n"
         "     payload      : length = %zu, padding = %zu (total: %zu)\n"
         "  Total : %d\n"
         "  Message : %zu\n"
         "Total : %d\n",
         headerStructLength,
         sizeOfLength,
         payloadLength, padding, payloadLength + padding,
         structLength,
         messageLength,
         bufferLength
  );

  buffer = malloc((size_t) bufferLength);

  /* setting up payload */
  nameValueLength = (MQLONG) payloadLength;
  pNameValueData = (PMQCHAR) (buffer + MQRFH_STRUC_LENGTH_FIXED_2 + sizeOfLength);
  memcpy(pNameValueData, payload, (size_t) nameValueLength);

  p = pNameValueData + nameValueLength;
  for (i = 0; i < padding; i++)
  {
    *p = ' ';
    p++;
    nameValueLength++;
  }

  /* setting up valueLength */
  pNameValueLength = (PMQINT32) (buffer + MQRFH_STRUC_LENGTH_FIXED_2);
  *pNameValueLength = nameValueLength;

  /* setting up message */
  pMessage = pNameValueData + nameValueLength;
  memcpy(pMessage, message, messageLength);

  /* setting up header */
  pHeader = (PMQRFH2) buffer;
  memcpy(pHeader, &DefaultHeader, MQRFH_STRUC_LENGTH_FIXED_2);
  memcpy(pHeader->Format, MQFMT_STRING, MQ_FORMAT_LENGTH);
  pHeader->CodedCharSetId = MQCCSI_INHERIT;
  pHeader->NameValueCCSID = 1208;
  pHeader->StrucLength = (MQLONG) (headerStructLength + sizeOfLength + nameValueLength); /* !!! */

  /* seeting up for put */
  memcpy(md.Format, MQFMT_RF_HEADER_2, MQ_FORMAT_LENGTH);
  md.MsgType = MQMT_DATAGRAM;
  md.Persistence = MQPER_PERSISTENT;

  pmo.Options = pmo.Options | MQPMO_NEW_MSG_ID | MQPMO_NO_SYNCPOINT;

  MQPUT(*connectionDescriptorPtr, *queueDescriptorPtr, &md, &pmo, bufferLength, buffer, &completionResult, &reason);
  free(buffer);
  printf("Message put in queue with code %d and reason %d\n", completionResult, reason);

  return 0;
}

我使用上面的代码来设置要发送的缓冲区。 问题被缩小到以下情况:

1)如果我没有在标题中设置StrucLength字段(与!!!一起排队),则消息正在成功放入队列并携带可在消息浏览器中读取的正确格式和数据

2)如果我像在代码中那样设置正确计算的字段,则将消息放入队列中,但显示为没有MQRFH2标头数据的MQSTR消息类型

3)如果我设置的字段计算错误,那么我会得到2142原因代码,这显然是问题的根源。

现在所有这些都让我产生了一个问题: 如果我发出消息,我不应该手动填充StrucLength字段吗?

1 个答案:

答案 0 :(得分:2)

对于您的问题的简短回答是,如果您以上述方式创建RFH2标头,则需要设置长度。 RFH2标头的长度可以变化。默认长度为MQRFH_STRUC_LENGTH_FIXED_2。

关于为什么它没有正确显示我不能很好地理解为什么会这样。

我会推荐一些RFH2代码示例供您查看。可以在安装目录中找到这些示例,例如:C:\ Program Files \ IBM \ WebSphere MQ \ Tools \ c \ Samples \ pubsub \ amqsgr2a.c。 pubsub目录中的示例具有构建RFH2头函数。在这些示例中,明确设置长度。在获取和初始化存储时,它们采用的方法略有不同。

还有MQSETMP api,我相信可以用来修改RFH2头。此api还可以在RFH2标头中维护和设置您的长度。我还没有找到它的用法示例。

希望这有帮助。