三言两语

MSMQ消息队列使用若干问题

需要实现互联网上两个C#程序间的数据交换。

需求

  1. 发送数据的程序位于机器A,接收数据的程序位于机器B;
  2. 接收数据的程序由第三方实现,需要的数据处理尽可能简单,由A程序实现方提供示例代码;
  3. 程序均采用C#实现,A方程序采集的数据是json格式,需要选取一些字段内容传给B方;
  4. 数据结构采用C#的struct/class方式定义。

想到的方案有Socket,消息队列等。Socket实现略显复杂,需要考虑到消息缓存队列、采集数据、维护连接等,包括多线程同步等问题,决定采用消息队列,实现起来会简化很多问题,MSMQ成了自然之选。

使用C#程序(A方)往远程MSMQ私有队列发送消息

  1. 根据采集到的json内容格式,定义相关数据结构,即C#的class,Record;
  2. 将采集到的json内容反序列化到C#的对象record(Record的实例);
  3. 选取record的部分字段,赋值给另一个表示消息的C#对象recordmessage;
  4. 创建对应远程消息队列的对象;
  5. 发送消息对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Record
{
public int x;
public string[] y;
}
string json = ...;
Record record = Newtonsoft.Json.JsonConvert.DeserializeObject<Record>(json);
...
mq = new MessageQueue("FormatName:Direct=TCP:135.101.101.101\\private$\\MyMSMQ");
mq.Formatter = new BinaryMessageFormatter();
mq.Send(record, "Object message");

使用C#程序(B方)从远程MSMQ私有队列接收消息

  1. C#项目中添加引用,添加由A方提供的包含Record定义的DLL - MyDLL.dll;
  2. 创建对应远程消息队列的对象;
  3. 从该远程消息队列接收消息,消息体类型为C# Record类的实例record。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mq = new MessageQueue("FormatName:Direct=TCP:135.101.101.101\\private$\\MyMSMQ");
mq.Formatter = new BinaryMessageFormatter();
try
{
System.Messaging.Message m = mq.Receive();
Record record = (MyDLL.Record)m.Body;
}
catch (MessageQueueException ee)
{
Console.Write(ee.ToString());
}
catch (Exception eee)
{
Console.Write(eee.ToString());
}
finally
{
mq.Close();
}

主要问题

  1. 远程MSMQ队列的标识:”FormatName:Direct=TCP:IpAddr\private$\QueueName”
  2. 当从远程MSMQ私有队列接收消息时,报出accessdenied的exception。原来是远程消息队列的机器中,需要在计算机管理 -> 服务和应用程序 -> 消息队列 点击右键,属性 -> 服务器安全性 页,去掉禁用未经身份验证的RPC调用。那前面发送消息为何成功呢?因为send和receive采用不同的协议,receive是采用RPC调用的方式。

热评文章