使用IBM MQ发送消息,获取2059错误或挂起构建队列管理器

时间:2017-11-10 13:10:28

标签: c# ibm-mq

我的任务是将测试消息发送到(当前)未知的MQ端点。

我在服务器上放置了IBM WebSphere MQ(v8.0.0.5)的试用版,我相信已正确配置。

但是,考虑到下面的代码,我得到了例外:

  

类型' IBM.WMQ.MQException'的未处理异常发生在   amqmdnet.dll

     

其他信息:2059

或者,如果我使用localhost而不是远程服务器名称在服务器上,则构造函数行会挂起。

这是C#:

Hashtable connectionProperties = new Hashtable();

string connectionType = MQC.TRANSPORT_MQSERIES_MANAGED
connectionProperties.Add(MQC.TRANSPORT_PROPERTY, connectionType);

// Set up the rest of the connection properties, based on the
// connection type requested
switch (_connectionType)
{
    case MQC.TRANSPORT_MQSERIES_BINDINGS:
        break;
    case MQC.TRANSPORT_MQSERIES_CLIENT:
    case MQC.TRANSPORT_MQSERIES_XACLIENT:
    case MQC.TRANSPORT_MQSERIES_MANAGED:
        connectionProperties.Add(MQC.HOST_NAME_PROPERTY, "server.com");
        connectionProperties.Add(MQC.CHANNEL_PROPERTY, "SYSTEM.DEF.CLNTCONN");      
        break;
}

MQQueueManager qMgr = new MQQueueManager("test", connectionProperties);
MqClientTest mqClientTest=new MqClientTest("TEST_QM","localhost", "SYSTEM.DEF.CLNTCONN");

我们还有什么遗漏吗?

更新1:

amqerr01.log文件夹的errors文件中,我们现在有文字:

  

AMQ6183:发生了内部WebSphere MQ错误。

更新2:

"内部WebSphere MQ错误"很可能是因为我在探测1414港口,看看港口是否是#34; up"和听。似乎它是,它显然不喜欢我这样做。

更新3:

@Roger建议我使用127.0.0.1和我现在应用的大写字母 - 并更改上面的示例以反映。

@JoshMc指出Queue Manager文件夹中的第二个AMQERR01.LOG文件。我现在得到错误:

  

14/11/2017 15:35:08 - 流程(336.6)用户(xxxx)   计划(amqrmppa.exe)                         主机(xxxx)安装(xxxx)                         VRMF(8.0.0.5)QMgr(TEST_QM)                         AMQ9519:频道' SYSTEM.DEF.CLNTCONN'没找到。

     

说明:请求的操作失败,因为程序可以   找不到频道的定义' SYSTEM.DEF.CLNTCONN'。

TEST_QM是我的队列管理器,默认(?)频道SYSTEM.DEF.CLNTCONN

2 个答案:

答案 0 :(得分:1)

使用IBM MQ,总会有一对可以协同工作的通道。例如,如果一个MQ队列管理器需要向另一个队列管理器发送消息,则通常会定义SDR(发送者)通道,该通道将指向具有相同名称的RCVR(接收器)通道在另一个队列管理器上。

对于MQ客户端连接,通道的客户端应用程序端称为MQCD,MQ队列管理器端称为SVRCONN(服务器连接)通道。客户端MQCD可以通过几种不同的方式指定。您在发布的示例中演示的方式是以编程方式指定MQCD信息(频道名称,主机名等)。

指定信息的另一种方法是指向CCDT(客户端信道定义表),通常称为信道表,这是使用CLNTCONN信道的地方,由于您没有使用频道表,我将继续讨论您收到错误的原因,但在此答案的最后,我将提供有关频道表的更多详细信息。

总之,您的应用应该指定CLNTCONN频道,因为MQC.CHANNEL_PROPERTY频道应该指向SVRCONN频道。

有两点需要注意:

  1. 您不应为此目的使用预定义的SYSTEM.*频道(例如SYSTEM.DEF.SVRCONN),您应为应用程序定义一个新频道供您使用。默认通道用于保存在创建相同类型的新通道时要作为默认值的参数。
  2. MQ v7.1及更高版本默认启用了一些CHLAUTH规则,这将禁止访问SYSTEM.*个频道。
  3. 如果要在Windows上使用命令行程序SVRCONN定义runmqsc频道,请在CMD提示符上运行以下命令:

    echo DEFINE CHL(TEST_QM_CHANNEL1) CHLTYPE(SVRCONN)|runmqsc TEST_QM
    

    关于频道表的更多细节:

    在MQ v8之前,唯一支持生成通道表的方法是在队列管理器上定义CLNTCONN个通道,在名为{的目录中的队列管理器名称文件夹下创建一个名为AMQCLCHL.TAB的文件。 {1}}。队列管理器附带名为@ipcc的频道的原因是在您创建新的SYSTEM.DEF.CLNTCONN频道时提供默认值。使用v8及更高版本,您可以仅使用CLNTCONN模式创建通道表,这将直接编辑通道表,而不是需要在队列管理器上创建runmqsc -n通道。 MQ Client for v8及更高版本现在提供了CLNTCONN的客户端版本,可用于创建和更改通道表。

    应用程序可以通过几种不同的方式指向通道表文件,常见的方法是设置两个环境变量(runmqscMQCHLLIB)。然后应用程序不在程序中指定通道名称,主机名等,它只需要指定要连接的队列管理器的名称。

    IBM v7.5(或更高版本)知识中心页面“Connecting IBM WebSphere MQ MQI client applications to queue managers”中记录了MQ查找连接信息的顺序和位置。请注意,此链接适用于MQI客户端,但同样的基本顺序也适用于.NET客户端。

答案 1 :(得分:0)

  

本地主机

尝试使用127.0.0.1而不是localhost。

  

“rx”和“swift_test_tx”

由于您不熟悉MQ,现在是时候阅读MQ Best Practices了。一个项目是对MQ对象名称使用小写字符不是一个好主意。即队列,通道等... MQ将始终将任何不在引号中的名称折叠为大写。因此,最好先将名称大写(以后减少问题)。

接下来,您是否在防火墙中打开了端口1414?如果没有,则打开TCP&的端口。 UDP。

以下是将消息放入远程队列管理器中的队列的C#程序示例:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using IBM.WMQ;

/// <summary> Program Name
/// MQTest51
///
/// Description
/// This C# class will connect to a remote queue manager
/// and put a message to a queue under a managed .NET environment.
///
/// Sample Command Line Parameters
/// -h 127.0.0.1 -p 1414 -c TEST.CHL -m MQWT1 -q TEST.Q1
///
/// </summary>
namespace MQTest51
{
   class MQTest51
   {
      private Hashtable inParms = null;
      private Hashtable qMgrProp = null;
      private System.String qManager;
      private System.String outputQName;

      /*
      * The constructor
      */
      public MQTest51()
         : base()
      {
      }

      /// <summary> Make sure the required parameters are present.</summary>
      /// <returns> true/false
      /// </returns>
      private bool allParamsPresent()
      {
         bool b = inParms.ContainsKey("-h") && inParms.ContainsKey("-p") &&
                  inParms.ContainsKey("-c") && inParms.ContainsKey("-m") &&
                  inParms.ContainsKey("-q");
         if (b)
         {
            try
            {
               System.Int32.Parse((System.String)inParms["-p"]);
            }
            catch (System.FormatException e)
            {
               b = false;
            }
         }

         return b;
      }

      /// <summary> Extract the command-line parameters and initialize the MQ variables.</summary>
      /// <param name="args">
      /// </param>
      /// <throws>  IllegalArgumentException </throws>
      private void init(System.String[] args)
      {
         inParms = Hashtable.Synchronized(new Hashtable());
         if (args.Length > 0 && (args.Length % 2) == 0)
         {
            for (int i = 0; i < args.Length; i += 2)
            {
               inParms[args[i]] = args[i + 1];
            }
         }
         else
         {
            throw new System.ArgumentException();
         }

         if (allParamsPresent())
         {
            qManager = ((System.String)inParms["-m"]);
            outputQName = ((System.String)inParms["-q"]);

            qMgrProp = new Hashtable();

            qMgrProp.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);

            qMgrProp.Add(MQC.HOST_NAME_PROPERTY, ((System.String)inParms["-h"]));
            qMgrProp.Add(MQC.CHANNEL_PROPERTY, ((System.String)inParms["-c"]));

            try
            {
               qMgrProp.Add(MQC.PORT_PROPERTY, System.Int32.Parse((System.String)inParms["-p"]));
            }
            catch (System.FormatException e)
            {
               qMgrProp.Add(MQC.PORT_PROPERTY, 1414);
            }

            if (inParms.ContainsKey("-u"))
               qMgrProp.Add(MQC.USER_ID_PROPERTY, ((System.String)inParms["-u"]));

            if (inParms.ContainsKey("-x"))
               qMgrProp.Add(MQC.PASSWORD_PROPERTY, ((System.String)inParms["-x"]));

            if ( (inParms.ContainsKey("-u")) && (inParms.ContainsKey("-x")) )
               qMgrProp.Add(MQC.USE_MQCSP_AUTHENTICATION_PROPERTY, true);
         }
         else
         {
            throw new System.ArgumentException();
         }
      }

      /// <summary> Connect, open queue, write a message, close queue and disconnect.
      ///
      /// </summary>
      /// <throws>  MQException </throws>
      private void testSend()
      {
         System.String line;
         int openOptions = MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING;

         try
         {
            MQQueueManager _qMgr = new MQQueueManager(qManager, qMgrProp);
            System.Console.Out.WriteLine("MQTest51 successfully connected to " + qManager);

            MQQueue queue = _qMgr.AccessQueue(outputQName, openOptions, null, null, null); // no alternate user id
            System.Console.Out.WriteLine("MQTest51 successfully opened " + outputQName);

            MQPutMessageOptions pmo = new MQPutMessageOptions();

            // Define a simple MQ message, and write some text in UTF format..
            MQMessage sendmsg = new MQMessage();
            sendmsg.Format = MQC.MQFMT_STRING;
            sendmsg.Feedback = MQC.MQFB_NONE;
            sendmsg.MessageType = MQC.MQMT_DATAGRAM;

            line = "This is a test message embedded in the MQTest51 program.";

            sendmsg.MessageId = MQC.MQMI_NONE;
            sendmsg.CorrelationId = MQC.MQCI_NONE;
            sendmsg.WriteString(line);

            // put the message on the queue

            queue.Put(sendmsg, pmo);
            System.Console.Out.WriteLine("Message Data>>>" + line);

            queue.Close();
            System.Console.Out.WriteLine("MQTest51 closed: " + outputQName);
            _qMgr.Disconnect();
            System.Console.Out.WriteLine("MQTest51 disconnected from " + qManager);
         }
         catch (MQException mqex)
         {
            System.Console.Out.WriteLine("MQTest51 cc=" + mqex.CompletionCode + " : rc=" + mqex.ReasonCode);
         }
         catch (System.IO.IOException ioex)
         {
            System.Console.Out.WriteLine("MQTest51 ioex=" + ioex);
         }
      }

      /// <summary> main line</summary>
      /// <param name="args">
      /// </param>
      //        [STAThread]
      public static void Main(System.String[] args)
      {
         MQTest51 write = new MQTest51();

         try
         {
            write.init(args);
            write.testSend();
         }
         catch (System.ArgumentException e)
         {
            System.Console.Out.WriteLine("Usage: MQTest51 -h host -p port -c channel -m QueueManagerName -q QueueName [-u userID] [-x passwd]");
            System.Environment.Exit(1);
         }
         catch (MQException e)
         {
            System.Console.Out.WriteLine(e);
            System.Environment.Exit(1);
         }

         System.Environment.Exit(0);
      }
   }
}