c#或java发送MSMQ远程消息
其实我在工作中从来没用过微软的东西,写这篇文章的原因是,同事的项目遇到了MSMQ远程发送消息的问题,所以我试着帮忙摸索了一下,然后把我的步骤写在这里以供参考。
1 MSMQ的安装
我的电脑环境为win10,在win10上安装MSMQ很简单,只需要鼠标点点点就好了。
控制面板->程序->启用或关闭Windows功能
在弹出框中找到MSMQ服务器选项,勾选。这里注意一定要勾选成功其中的“MSMQ HTTP 支持”框。点击确定,会自动安装。

右键“此电脑”,点击“管理”,如果在“服务和应用程序”中看到下图中的消息队列,说明安装成功。

在浏览器中访问http://localhost
如果看到下图页面,说明已经启动好了IIS服务,支持HTTP协议发送消息了

2 创建mq
用本地访问的方式,创建一个专有队列kkkMQ
下面的是c#代码,可命名为server.cs
编译csc server.cs
,会生成server.exe文件。启动后,会在服务中看到新增了kkkMQ队列,而且第一条消息为susu~
using System;
using System.Messaging;
namespace MSMQServer
{
class Program
{
static void Main(string[] args)
{
// 创建一个私有消息队列
if (!MessageQueue.Exists(@".\Private$\kkkMQ"))
{
using (MessageQueue mq = MessageQueue.Create(@".\Private$\kkkMQ"))
{
mq.Label = "susuMSMQPrivateQueue";
Console.WriteLine("已经创建了一个susuMSMQ私有队列!");
Console.WriteLine("队列路径为:{0}", mq.Path);
Console.WriteLine("私有队列名字为:{0}", mq.QueueName);
mq.Send("(create) MSMQ Private Message", "susu~"); // 发送消息
}
}
Console.Read();
}
}
}
3 C#客户端发送消息
使用客户端发送消息
- 本地发送
MessageQueue mq = new MessageQueue(@".\Private$\susuMSMQ");
- tcp发送
new MessageQueue(@"FormatName:Direct=tcp:localhoost\Private$\kkkMQ");
- 局域网发送
new MessageQueue(@"FormatName:Direct=http://localhost/msmq/Private$/kkkMQ");
- 局域网发送
new MessageQueue(@"FormatName:Direct=http://192.168.1.7/msmq/Private$/kkkMQ");
- 使用内网穿透域名发送
new MessageQueue(@"FormatName:Direct=http://susumsmq.frpgz1.idcfengye.com/msmq/Private$/kkkMQ");
内网穿透我是在ngrok.cc网站,花10块RMB买了一个frp服务器
- 域名为:susumsmq.frpgz1.idcfengye.com
- 启动方式
sunny.exe --clientid=隧道ID
这里还要考虑穿透防火墙,路由等障碍
设置服务器端(即本机)的
C:\WINDOWS\system32\msmq\mapping\sample_map.xml
这个文件
<!--
This is a sample XML file that demonstrates queue redirection. Use it as a
template to create your own queue redirection files.
-->
<redirections xmlns="msmq-queue-redirections.xml">
<!--
Each <Redirections> element contains 0 or more <redirection> elements, each
of which contains exactly one <from> subelement and exactly one <to>
subelement. Each <redirection> element describes a redirection (or mapping)
of the logical address given in the <from> subelement to the physical address
given in the <to> element.
<redirection>
<from>http://external_host/msmq/external_queue</from>
<to>http://internal_host/msmq/internal_queue</to>
</redirection>
-->
<!--
Limited use of regular expressions in a <from> element is supported.
Asterisk-terminated URLs can define a redirection from multiple logical
addresses to a single physical address.
In the following example, any message with a logical address that starts
with the string https://external_host/* will be redirected to the physical
address in the <to> element.
<redirection>
<from>https://external_host/*</from>
<to>http://internal_host/msmq/internal_queue</to>
</redirection>
-->
<redirection>
<from>http://susumsmq.frpgz1.idcfengye.com/*</from>
<to>http://localhost/msmq/Private$/kkkmq</to>
</redirection>
</redirections>
配置完上面的路由后,在服务中找到MSMQ,右键重启

重启后,用上面提到的方法重新创建kkkMQ队列,即再次运行server.exe
接着将下方代码保存为client.cs
用csc client.cs
编译成exe执行文件
运行client.exe文件,你会发现远程消息发送成功
using System;
using System.Messaging;
namespace MSMQServer
{
class Program
{
static void Main(string[] args)
{
// 获得私有消息队列
MessageQueue mq2 = new MessageQueue(@"FormatName:Direct=http://susumsmq.frpgz1.idcfengye.com/msmq/Private$/kkkMQ");
mq2.Send("frpgz1!!(Send) Sending MSMQ private message" + DateTime.Now.ToLongDateString(), "frpgz1-kkkMQ-remotesusu~");
Console.WriteLine("frpgz1!! :Private Message is sent to {0}", mq2.Path);
}
}
}
4 JAVA发送远程消息
https://archive.codeplex.com/?p=msmqjava
试了一下这个官网很坑,下载下来的没有打包好的jar包,然后我用了网上其他地方下载的JAR包,发现Queue.Access
这个内部类没有打包出来,用不了
于是我将源代码中的Queue.java
单独放在项目src文件夹中的ionic.Msmq
包路径下,这样就可以用到Queue.Access
了
当然也可以选择重新编译jar包
在下面的代码中,如果用的是网上传的jar包,大多数情况下Queue queue = new Queue(fullname, Queue.Access.SEND);
这里会报错的
package test;
import ionic.Msmq.Message;
import ionic.Msmq.MessageQueueException;
import ionic.Msmq.Queue;
public class SimpleSendMSMQ {
public static void main(String[] args) {
try {
String fullname = "Direct=http://susumsmq.frpgz1.idcfengye.com/msmq/Private$/kkkMQ";
System.out.println(fullname);
Queue queue = new Queue(fullname, Queue.Access.SEND);
//标题
String label = "testSend";
//内容
String body = "Hello, World!";
byte[] correlationId = {0, 2, 4, 6, 8, 9};
// //创建消息
Message msg = new Message(body, label, correlationId);
queue.send(msg);
System.out.println("发送消息:" + msg.getLabel() + "," + msg.getBodyAsString());
} catch (MessageQueueException ex1) {
System.out.println("Put failure: " + ex1.toString());
ex1.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}