尝试使用PHP连接MQ,即将成功。

8

最近几天,我一直在尝试解决这个似乎被遗忘的问题,因为两个可用的PECL扩展(SAM和mqseries)都很长时间没有更新了。我已经尝试过这两个扩展,目前看来mqseries似乎可以让我走得更远,因为SAM拒绝连接,即使MQ命令行工具完美运行。我成功地创建了一个与我的队列管理器的连接,在下一步(MQOPEN)中,我惨败了:

$mqcno = array(
        'Version' => MQSERIES_MQCNO_VERSION_2,
        'Options' => MQSERIES_MQCNO_STANDARD_BINDING,
        'MQCD' => array('ChannelName' => '[channel]',
        'ConnectionName' => '[ipnumber]([port])',
        'TransportType' => MQSERIES_MQXPT_TCP)
    );

mqseries_connx('MQED', $mqcno, $conn, $comp_code,$reason);
if ($comp_code !== MQSERIES_MQCC_OK) {
    printf("Connx CompCode:%d Reason:%d Text:%s<br>\n", $comp_code, $reason, $reason);
    exit;
}

$mqods = array('ObjectName'=>'MYPUTQUEUE', 'ObjectType'=>MQOT_Q, 'ObjectQMgrName'=>'MYQUEUEMANAGER');
mqseries_open($conn, $mqods, 
          MQSERIES_MQOO_FAIL_IF_QUIESCING | MQSERIES_MQOO_OUTPUT,
          $obj, $comp_code,$reason);

这导致$reason被填充为2044,它对应于MQRC_OD_ERROR,或者用英语说:'在MQOPEN或MQPUT1调用中,对象描述符MQOD无效'。
所以问题是,我的MQOD有什么问题?
更新#1:目前这个问题还没有解决。我从头开始重建了项目,以解决构建时可能出现的任何问题。我仍然卡在MQOPEN返回2044上。样例在CLI中仍然运行得非常顺畅,因此这肯定与PECL扩展的安装有关。如果有人成功地在相当近期的64位PHP5环境中安装并运行PHP针对MQ,请告诉我...
更新#2:MQPUT1可以完美地工作,但我无法接收响应。目前,只有MQOPEN不起作用。问题是:当MQPUT1工作时,导致MQOPEN返回2044的原因是什么?我理解MQOPEN包括在内。

我已经成功地连接到我的队列管理器,但在下一步(MQCONN)中我惨败了...你是不是指的是它在MQOpen时失败了? - T.Rob
1
是的,抱歉。我已经编辑了我的问题。 - eriben
我不熟悉PHP模块,但“DeviceName”似乎是队列名称的奇怪键。 - T.Rob
也许这就是问题所在。但是官方示例是这样做的:http://www.php.net/manual/en/function.mqseries-open.php - eriben
但在该示例中,哈希键是ObjectName,它与cmqc.h字段名称匹配。DeviceName从哪里来的? - T.Rob
我之前就有了,但是没有任何区别。现在我正在遍历整个结构体,看看是否有我忘记的东西。但是,如果 Objectname 是我的 PUT 队列,那么 ObjectType 是什么? - eriben
1个回答

1

在 cmqch 文件中,MQOD 看起来像这样:

 /****************************************************************/
 /*  MQOD Structure -- Object Descriptor                         */
 /****************************************************************/


 typedef struct tagMQOD MQOD;
 typedef MQOD  MQPOINTER PMQOD;
 typedef PMQOD MQPOINTER PPMQOD;

 struct tagMQOD {
   MQCHAR4   StrucId;              /* Structure identifier */
   MQLONG    Version;              /* Structure version number */
   MQLONG    ObjectType;           /* Object type */
   MQCHAR48  ObjectName;           /* Object name */
   MQCHAR48  ObjectQMgrName;       /* Object queue manager name */
   MQCHAR48  DynamicQName;         /* Dynamic queue name */
   MQCHAR12  AlternateUserId;      /* Alternate user identifier */
   /* Ver:1 */
   MQLONG    RecsPresent;          /* Number of object records
                                      present */
   MQLONG    KnownDestCount;       /* Number of local queues opened
                                      successfully */
   MQLONG    UnknownDestCount;     /* Number of remote queues opened
                                      successfully */
   MQLONG    InvalidDestCount;     /* Number of queues that failed to
                                      open */
   MQLONG    ObjectRecOffset;      /* Offset of first object record
                                      from start of MQOD */
   MQLONG    ResponseRecOffset;    /* Offset of first response record
                                      from start of MQOD */
   MQPTR     ObjectRecPtr;         /* Address of first object record */
   MQPTR     ResponseRecPtr;       /* Address of first response
                                      record */
   /* Ver:2 */
   MQBYTE40  AlternateSecurityId;  /* Alternate security identifier */
   MQCHAR48  ResolvedQName;        /* Resolved queue name */
   MQCHAR48  ResolvedQMgrName;     /* Resolved queue manager name */
   /* Ver:3 */
   MQCHARV   ObjectString;         /* Object long name */
   MQCHARV   SelectionString;      /* Message Selector */
   MQCHARV   ResObjectString;      /* Resolved long object name*/
   MQLONG    ResolvedType;         /* Alias queue resolved object type */
   /* Ver:4 */
 };

 #define MQOD_DEFAULT {MQOD_STRUC_ID_ARRAY},\
                      MQOD_VERSION_1,\
                      MQOT_Q,\
                      {""},\
                      {""},\
                      {"AMQ.*"},\
                      {""},\
                      0,\
                      0,\
                      0,\
                      0,\
                      0,\
                      0,\
                      NULL,\
                      NULL,\
                      {MQSID_NONE_ARRAY},\
                      {""},\
                      {""},\
                      {MQCHARV_DEFAULT},\
                      {MQCHARV_DEFAULT},\
                      {MQCHARV_DEFAULT},\
                      MQOT_NONE

我在想这个模块是否填充了默认值并让你用哈希覆盖它们。如果是这样,'DeviceName' 是否真的是正确的键?我认为它应该匹配 WMQ 字段名称或常量。

更新:根据提供链接中示例,哈希键确实与 cmqc.h 中的字段名匹配。

更新#2 回复评论:在 cmqc.h 中定义的对象类型为:

 /* Object Types */
 #define MQOT_NONE       0
 #define MQOT_Q          1
 #define MQOT_NAMELIST   2
 #define MQOT_PROCESS    3
 #define MQOT_STORAGE_CLASS 4
 #define MQOT_Q_MGR      5
 #define MQOT_CHANNEL    6
 #define MQOT_AUTH_INFO  7
 #define MQOT_TOPIC      8
 #define MQOT_CF_STRUC   10
 #define MQOT_LISTENER   11
 #define MQOT_SERVICE    12
 #define MQOT_RESERVED_1 999

我对PHP、Perl和其他类似的编程语言的理解是,它们只是C API的一个非常薄的封装。Perl模块直接从cmqc.h和其他C包含文件中生成大部分代码,因此所有字段名称和默认值都与这些包含文件完全匹配。这个模块似乎采用了类似的方法,我期望在需要时使用定义的名称和字段默认值。

我的想法是:

$mqods = array(
                 'StrucID'=>'OD  ',
                 'Version'=>1.
                 'ObjectType'=>1,
                 'ObjectName'=>'MYPUTQUEUE', 
                 'ObjectQMgrName'=>'MYQUEUEMANAGER'
                 'DynamicQName'='',
                 'AlternateUserId'='',
                 'RecsPresent'=>0,
                 'KnownDestCount'=>0,
                 'UnknownDestCount'=>0,
                 'InvalidDestCount'=>0,
                 'ObjectRecOffset'=>0,
                 'ResponseRecOffset'=>0,
                 'ObjectRecPtr'=>NULL,
                 'ResponseRecPtr'=>NULL
);

更新 #3 响应其他评论:

Q 管理器将接受任何版本的 MQOD,但会退回到该功能级别。 如果您使用 v1,则可以测试它是否正常工作。 如果要使用较新版本的 MQOD,则需要将其他字段添加到哈希中。

2009 是“连接断开”。 基本上,Q 管理器不喜欢某些东西并终止了您的连接。 通常,该返回代码的有意义的错误消息存储在 /var/mqm/qmgrs/<qmgrname>/errors/AMQEER01.LOG 中。


他们这样做了。将哈希表更改为以下内容,但没有成功:$mqods = array('ObjectName'=>'MYPUTQUEUE', 'ObjectType'=>MQOT_Q, 'ObjectQMgrName'=>'MYQUEUEMANAGER'); - eriben
除非定义了常量MQOT_Q,否则该值将为1。 - T.Rob
将版本更改为4会导致另一个错误;2009年,这至少意味着它接受MQOD。如果我正确阅读cmqc.h,则4表示“当前版本”。 - eriben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接