项目中需要用java访问远端的msmq,从网上找了一个开源的实现:
http://msmqjava.codeplex.com
使用上一波三折,经过分析验证,打开队列采用不同的AccessMode,会决定访问远端的不同接口,佩服微软提供的API,竟然有如此威力。
现记录下分析的主要内容,以备查找。
MSMQ端口
http://support2.microsoft.com/kb/178517
Opening Queues
http://msdn.microsoft.com/en-us/library/ms706937(v=vs.85).aspx
Opening Remote Queues with Send Access
http://msdn.microsoft.com/en-us/library/ms705186(v=vs.85).aspx
此时采用的端口根据实际验证,应该只采用1801端口。
Opening Remote Queues with Peek or Receive Access
http://msdn.microsoft.com/en-us/library/ms699862(v=vs.85).aspx
此时采用的端口根据实际验证,包括135端口。
封装内容解析
参见下述组件中的程序源码:
http://msmqjava.codeplex.com/
封装的内容如下所示,根据access决定如何openQueue(),根据代码看,如果是创建Queue不传递参数,则为
OpenQueueWithAccess(jniEnv, object, queuePath, MQ_SEND_ACCESS | MQ_RECEIVE_ACCESS);
此时,MQ_SEND_ACCESS | MQ_RECEIVE_ACCESS=3
按照下面代码分析,如果MQ_SEND_ACCESS、MQ_RECEIVE_ACCESS同时设置,按MQ_RECEIVE_ACCESS 的openQueue()方式处理...
jint OpenQueueWithAccess
(JNIEnv *jniEnv, jobject object, jstring queuePath, int access)
{
jclass cls = jniEnv->GetObjectClass(object);
jfieldID fieldId;
HRESULT hr;
try {
MsmqQueue * sender= NULL;
MsmqQueue * receiver= NULL;
const char *szQueuePath = jniEnv->GetStringUTFChars(queuePath, 0);
DIAG("OpenQueueWithAccess (%s)\n", szQueuePath );
if (access & MQ_RECEIVE_ACCESS) {
receiver = new MsmqQueue();
// dinoch - Wed, 11 May 2005 13:48
// MQ_ADMIN_ACCESS == use the local, outgoing queue for remote queues. ??
hr = receiver->openQueue((char *) szQueuePath, MQ_RECEIVE_ACCESS ); // | MQ_ADMIN_ACCESS
if (hr != 0) {
delete receiver;
return hr;
}
}
if (access & MQ_SEND_ACCESS) {
sender = new MsmqQueue();
// dinoch - Wed, 11 May 2005 13:48
// MQ_ADMIN_ACCESS == use (local) outgoing queue for remote queues
hr = sender->openQueue((char *) szQueuePath, MQ_SEND_ACCESS ); // | MQ_ADMIN_ACCESS
if (hr != 0) {
delete sender;
if (receiver!=NULL) delete receiver;
return hr;
}
}
jniEnv->ReleaseStringUTFChars(queuePath, szQueuePath);
int slot= StoreHandles(receiver, sender);
if (slot == -1) return -2;
// use JNI to set the _queueSlot field on the caller
fieldId = jniEnv->GetFieldID(cls, "_queueSlot", "I");
if (fieldId == 0) return -3;
jniEnv->SetIntField(object, fieldId, (jint)slot);
}
catch(...) {
DIAG("openQueue : Exception. \n");
jniEnv->ExceptionDescribe();
jniEnv->ExceptionClear();
hr = -99;
}
fflush(stdout);
return (jint) hr;
}