我的任务是将测试消息发送到(当前)未知的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
答案 0 :(得分:1)
使用IBM MQ,总会有一对可以协同工作的通道。例如,如果一个MQ队列管理器需要向另一个队列管理器发送消息,则通常会定义SDR
(发送者)通道,该通道将指向具有相同名称的RCVR
(接收器)通道在另一个队列管理器上。
对于MQ客户端连接,通道的客户端应用程序端称为MQCD
,MQ队列管理器端称为SVRCONN
(服务器连接)通道。客户端MQCD
可以通过几种不同的方式指定。您在发布的示例中演示的方式是以编程方式指定MQCD
信息(频道名称,主机名等)。
指定信息的另一种方法是指向CCDT
(客户端信道定义表),通常称为信道表,这是使用CLNTCONN
信道的地方,由于您没有使用频道表,我将继续讨论您收到错误的原因,但在此答案的最后,我将提供有关频道表的更多详细信息。
总之,您的应用应该不指定CLNTCONN
频道,因为MQC.CHANNEL_PROPERTY
频道应该指向SVRCONN
频道。
有两点需要注意:
SYSTEM.*
频道(例如SYSTEM.DEF.SVRCONN
),您应为应用程序定义一个新频道供您使用。默认通道用于保存在创建相同类型的新通道时要作为默认值的参数。CHLAUTH
规则,这将禁止访问SYSTEM.*
个频道。如果要在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
的客户端版本,可用于创建和更改通道表。
应用程序可以通过几种不同的方式指向通道表文件,常见的方法是设置两个环境变量(runmqsc
和MQCHLLIB
)。然后应用程序不在程序中指定通道名称,主机名等,它只需要指定要连接的队列管理器的名称。
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);
}
}
}