不同平台上 MQ 管理器上的 CCSID

CCSID on MQ Managers on different platforms

如果基于 Solaris 的 MQ 管理器将消息发送到中间 Windows MQ 管理器,然后再将消息发送到 Linux MQ 管理器,是否需要将它们的 CCSID 都更改为是相同的?我不这么认为,但我被迫这样做...

我遇到一个问题,客户端通过 Windows 上的中间 MQ 管理器从 Solaris 上的应用程序发送消息,但是 Linux 基于 MQ 管理器最终目标的应用程序收到消息 CR/LF 它无法处理的行结束字符。接收端组要不要写一个转换出口程序?还是 MCA?

我闻到您的 MQ 环境中有一个糟糕的设置,任何说要使它们完全相同的人都不知道或不理解 MQ(并且应该对配置零评价)。

此外,将发送者通道的 CONVERT 属性设置为 YES 是一个非常糟糕的主意,只能在极端情况下使用。有关详细信息,请参阅 IBM 最佳实践。只有当应用程序发出带有 Convert 的 MQGET 时才应该进行数据转换。

因为,Solaris 对 CR/LF 毫无头绪,我要猜测是哪里出了问题:

  • 消息的 MQMD 格式字段设置了 'MQSTR' 值。
  • Solaris 队列管理器之间的发送方通道将属性 CONVERT 设置为 YES
  • Linux 上的接收应用程序未发出 MQGET with Convert。

问题:

  1. Solaris 应用程序是否实际将消息放入 CR/lF?
  2. Solaris 应用程序是否将 MQMD 格式字段设置为 'MQSTR'?
  3. 为什么消息希望通过 Windows 队列管理器?为什么不在 Solaris 队列管理器和 Linux 队列管理器之间建立直接连接?
  4. Solaris 发送方通道的 CONVERT 属性有什么值?即是或否?

最简单的解决方案是让 Linux 应用程序发出带有 Convert 的 MQGET,假设 MQMD 格式字段设置为 'MQSTR'。 MQ会自动将消息数据转换到正确的平台。

如果 MQMD Formet 字段未设置为 'MQSTR',则 MQ 将不会在平台之间转换消息数据。这意味着 Solaris 应用程序将 CR/LF 放入消息中。我觉得这很难相信。如果开发人员这样做,那么他们真的不了解 MQ(并且不应该对其进行编程)。

IBM MQ 不处理换行。它不像 t运行 使用 ftp 传送文件并使用 ascii 模式,其中 ftp 将从 Unix LF 行尾转换为 Window CR 和 LF 行尾。对于 MQ,它只是 t运行slate 字符集中的另一个字符。如果发送应用程序正在发送包含 CR/LF 个字符的数据,MQ 会将它们视为数据中的任何其他字符。如果接收应用程序希望将带有行尾的文件作为 MQ 消息发送,则需要处理行尾。


Solaris 服务器上 Java 应用程序 运行 的

MQ 类 默认为 CCSID 819,Solaris 上的 IBM MQ 队列管理器 运行 也将默认为 CCSID 819. CCSID 819 被描述为 ISO 8859-1 ASCII.

我创建了一个名为 test.txt 的文件,其中包含单个单词 "test" 和 运行 unix2dos 文件。

下面的输出将 ASCII 字符显示为 HEX 值:

$cat test.txt | hexdump -C
00000000  74 65 73 74 0d 0a                                 |test..|
00000006

请注意,在上面的输出中,ASCII 十六进制值 0dCR0aLF,这些是常见的 Windows行尾。

如果我们假设默认的 CCSID 819 用于 Solaris MQ 类 for Java 应用程序和 Solaris 队列管理器,那么我们可以从假设以上两个开始十六进制值表示每行末尾的 CR/LF。

您声明您的 Windows 队列管理器具有 CCSID 437,这是美国 Windows 服务器的典型值。 CCSID 437 被描述为 USA PC-DATA 并且也是 ASCII。

Linux 队列管理器通常默认为 CCSID 1208。CCSID 1208 被描述为 UTF-8 with IBM PUA 并且是一个可变字节字符集,每个字符可以有 1 到 4 个字节。这可以表示超过一百万个字符,包括所有 ASCII 字符。所有 127 个 ASCII 字符在 UTF-8 中表示为与 ASCII 中相同的单字节十六进制值。

从 ASCII 到 UTF-8 的损失较少,如果使用非 ASCII 字符,从 UTF-8 到 ASCII 可能会有损失,因为 ASCII 中没有等效字符,MQ 将其​​转换为默认替换十六进制值 1A 的字符。例如,我已经看到这个带有欧元符号。大多数(如果不是全部)UTF-8 的前 255 个字符与 CCSID 819 相同。

鉴于上述 CCSID 假设,转换将如下所示:

Solaris 上 Java 应用程序 运行 的原始 IBM MQ 类 使用 CR/LF 行尾字符发送数据:

$cat test.txt | hexdump -C
00000000  74 65 73 74 0d 0a                                 |test..|
00000006

带有 CONVERT(YES) 发送到 Windows 带有 CCSID 437 的队列管理器的 Solaris 队列管理器发送器通道:

cat test.txt | iconv -f IBM819 -t IBM437 | hexdump -C
00000000  74 65 73 74 0d 0a                                 |test..|
00000006

正如预期的那样,输出是相同的,因为 819 和 437 都是 ASCII 字符集,并且数据不代表前 127 个 ASCII 字符以上的任何内容。

带有 CONVERT(YES) 发送到 Windows 队列管理器和 CCSID 437 的 Solaris 队列管理器发送器通道带有 CONVERT(YES) 发送到 Linux 带有 CCSID 1208 的队列管理器:

cat test.txt | iconv -f IBM819 -t IBM437 | iconv -f IBM437 -t UTF-8 | hexdump -C
00000000  74 65 73 74 0d 0a                                 |test..|
00000006

正如预期的那样,输出是相同的,因为 819 和 437 都是 ASCII 字符集,而 UTF-8 (1208) 的前 127 个字符是普通的 ASCII 字符。


总结:如果发送应用程序在数据中发送CR/LF,MQ 消息转换不会改变这一点,如果使用的 CCSID 是上面列出的 CCSID它甚至不会更改实际的十六进制字符值。发送应用程序需要更改它们发送的内容,或者接收应用程序需要容纳这些字符。


可以在文章“Unicode, UTF8 & Character Sets: The Ultimate Guide”中找到关于 ASCII、UNICODE、UTF-8 等的很好的参考。