6

我目前正在开发一个应用程序,它需要连接一个 MQ 队列,以便让队列在另一个服务中保存消息信息。完成后,服务会通过 MQ 队列返回一条结果消息并将其返回给我。

我正在发送一条包含类似于以下 XML 消息的字符串消息:

<?xml version="1.0" encoding="UTF-8"?>
<peticionDemanda>
<subtipo>DEMANDA CONTRATACIÓN</subtipo>
</peticionDemanda>

MQ 似乎没有正确解码“Ó”字符,并且“subtipo”字段被保存为“DEMANDA CONTRATACI├ôN”。

我将消息编码为“UTF-8”,并被告知用于发送消息的 CCSID 是 850 而不是 1208(属于 UTF-8 的那个)。

为了运行 MQ 管理器,我在客户端模式下使用“pymqi”Python 库。这是我用来向队列发送消息并获得响应的 MQManager 类:

class MQManager:
    def __init__(self):
        self.queue_manager = config.queue_manager
        self.channel = config.channel
        self.port = config.port
        self.host = config.host
        self.conn_info = config.conn_info
        self.queue_request_name = config.queue_request_name
        self.queue_response_name = config.queue_response_name

        cd = pymqi.CD()
        cd.ChannelName = self.channel
        cd.ConnectionName = self.conn_info
        cd.ChannelType = pymqi.CMQC.MQCHT_CLNTCONN
        cd.TransportType = pymqi.CMQC.MQXPT_TCP

        self.qmgr = pymqi.QueueManager(None)
        self.qmgr.connect_with_options(self.queue_manager, opts=pymqi.CMQC.MQCNO_HANDLE_SHARE_NO_BLOCK, cd=cd)

    def send_message(self, str_xml_message):
        # set message descriptor
        request_md = pymqi.MD()
        request_md.ReplyToQ = self.queue_response_name
        request_md.Format = pymqi.CMQC.MQFMT_STRING

        queue_request = pymqi.Queue(self.qmgr, self.queue_request_name)
        queue_request.put(str_xml_message.encode("UTF-8"), request_md)
        queue_request.close()

        # Set up message descriptor for get.
        response_md = pymqi.MD()
        response_md['CorrelId'] = request_md['MsgId']

        gmo = pymqi.GMO()
        gmo.Options = pymqi.CMQC.MQGMO_WAIT | pymqi.CMQC.MQGMO_FAIL_IF_QUIESCING
        gmo.WaitInterval = 5000  # 5 seconds

        queue_response = pymqi.Queue(self.qmgr, self.queue_response_name)
        message = queue_response.get_no_rfh2(None, response_md, gmo)
        queue_response.close()

        return str(message)


    def close(self):
        self.qmgr.disconnect()

我想知道如何定义 MQ 管理器的 CCSID 值并希望解决代码页不匹配的问题。

谢谢!

4

2 回答 2

3

在您的代码中,您为在这行代码中发送的消息创建默认消息描述符:

request_md = pymqi.MD()

默认情况下,pymqi(如底层 IBM MQ C 库)会将消息描述符设置CodedCharSetId为 value CMQC.MQCCSI_Q_MGR

这可以在源代码中看到:

['CodedCharSetId', CMQC.MQCCSI_Q_MGR, MQLONG_TYPE],

IBM MQ v9.0 KC 页面参考 > 开发应用程序参考 > MQI 应用程序参考 > Data types used in the MQI > MQMD - Message descriptor > Fields for MQMD > CodedCharSetId (MQLONG)描述了客户端如何处理此问题:

对于客户端应用程序,MQCCSI_Q_MGR 是根据客户端的语言环境而不是队列管理器上的语言环境来填充的。


IBM MQ 故障排除文档What CCSID 在默认情况下用于 WebSphere MQ 客户端消息以稍微不同的方式解释了这一点:

MQ 客户端根据客户端应用程序运行的环境设置 MQCCSI_Q_MGR 值。


基于850 CCSID,我猜您正在运行的 Windows 操作系统不在美国(通常使用 CCSID 437)。


您有几个选项可以覆盖它:

  1. 您可以像这样以编程方式覆盖 pymqi MQMD 默认值:

    request_md.CodedCharSetId = 1208
    
  2. 将 env 变量设置为MQCCSID您想要的值(在您的情况下为 1208)。这必须在连接到 mq 之前设置。这在 IBM MQ v9.0 KC 页面开发应用程序 > 使用 IBM MQ 开发 MQI 应用程序 > 编写客户端过程应用程序 > 在客户端应用程序中使用 MQI > 选择客户端或服务器 CCSID中进行了记录。

    以下示例适用于 Windows:

    SET MQCCSID=1208
    
  3. mqclient.ini您可以在CCSID=numberCHANNELS节下设置。这记录在 IBM MQ v9.0 KC 页面配置 > 配置服务器和客户端之间的连接 > 使用配置文件配置客户端 > 客户端配置文件的 CHANNELS 节中。例如:

    CHANNELS:
       CCSID=1208
    
于 2019-09-09T16:06:24.557 回答
2

您不需要更改队列管理器的 CCSID。您的问题是您的邮件包含 UTF-8 字符,但您已将其发送到一个信封中,将其描述为包含 CCSID 850 字符。您只需更新传递信息的信封即可正确描述您的内容。

我是 IBM MQ 专家和“C”程序员,但不是 pymqi 程序员,但是,查看 pymqi 帮助和您的示例,我希望这些是您的代码所需的补充。

# set message descriptor
request_md = pymqi.MD()
request_md.ReplyToQ = self.queue_response_name
request_md.Format = pymqi.CMQC.MQFMT_STRING
request_md.CodedCharSetId = 1208

CodedCharSetIdpymqi帮助不包括任何MQMD使用cmqc.h.

请试试这个,看看它是否能解决您的问题。

于 2019-09-09T23:00:46.160 回答