MSMQ + C#,接收带有编码的 byte[] 正文的消息在 Windows 7 和 Windows XP 上的行为不同
我有一个显示 MSMQ 消息队列中消息内容的应用程序。 Windows 7 上的 MSMQ 存在一个问题,即未保留消息正文中数据的真实对象类型。在示例中,我发送了一个 byte[],然后当我收到它时,它不再是一个字节数组,而是包装的 XML 容器文档。在 Windows XP 中我从未遇到过这个问题,并且 Message.Body 属性始终正确设置为 byte[]。
这是压缩代码:
public void SendWithCompression(string Message)
{
try
{
// Compress the message data in memory.
byte[] UncompressedData = Encoding.UTF8.GetBytes(Message);
byte[] CompressedData = null;
MemoryStream s = new MemoryStream();
using (GZipStream z = new GZipStream(s, CompressionMode.Compress))
{
z.Write(UncompressedData, 0, UncompressedData.Length);
}
CompressedData = s.ToArray();
if (_Transaction != null)
{
_Transaction.Begin();
base.Send(CompressedData, _Transaction);
_Transaction.Commit();
}
else
{
base.Send(CompressedData);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
这是测试消息的消息内容。它最终作为一个 XML 文档封装了编码的二进制数据: <代码>..
下面是它使用的解压代码:
String Data;
//Get message and format XML
System.Messaging.Message m = MessagesList[ListIndex].Tag;
m.Formatter = new XmlMessageFormatter(new Type[]
{
typeof(string), // Send raw plain strings
typeof(byte[]), // Array of binary data
typeof(XmlNode) // Xml document
});
m.BodyStream.Position = 0;
Data = m.Body.ToString();
if (m.Body.GetType() == typeof(byte[]))
{
try
{
// The message body is an array of binary data.
// Assume it is a GZIP stream of compressed data.
byte[] CompressedData = (byte[])m.Body;
byte[] UncompressedData = null;
// Decompress it.
MemoryStream s = new MemoryStream(CompressedData);
using (GZipStream z = new GZipStream(s, CompressionMode.Decompress))
{
UncompressedData = MyExtensions.ReadRemainingBytes(z);
}
// Turn the bytes back into a string.
Data = Encoding.UTF8.GetString(UncompressedData);
}
catch
{
Data = "Unknown binary data: " +
BitConverter.ToString((byte[])m.Body, 0);
}
}
if (m.Body.GetType() == typeof(XmlElement))
{
XmlElement el = (XmlElement)m.Body;
if (el.Name == "string")
Data = el.InnerText;
else
Data = el.OuterXml;
}
我想指出的是,我正在设置消息的 Formatter,这是让正文在队列中自动“装箱”和“拆箱”的第一步。
在 Windows XP 中,m.Body.GetType() == byte[],如预期的那样。但是,在 Windows 7 中,m.Body.GetType() == XmlElement,即包装器 XML。它不再“拆箱”消息。
我们需要做一些不同的事情吗?我们已经解决过一次发送字符串的问题,正如您在接收函数末尾看到的那样,但我想找到一个真正的答案来解释为什么这段代码在 Windows 7 上的行为不同。
I have an application that displays the contents of messages in an MSMQ message queue. There is a problem with MSMQ on Windows 7 not preserving the true object type of the data in the message body. In the example, I send a byte[], and then later when I receive it, it's no longer a byte array, but the wrapped XML container document. In Windows XP I have never had this problem, and the Message.Body property has always correctly been set to a byte[].
Here is the compression code:
public void SendWithCompression(string Message)
{
try
{
// Compress the message data in memory.
byte[] UncompressedData = Encoding.UTF8.GetBytes(Message);
byte[] CompressedData = null;
MemoryStream s = new MemoryStream();
using (GZipStream z = new GZipStream(s, CompressionMode.Compress))
{
z.Write(UncompressedData, 0, UncompressedData.Length);
}
CompressedData = s.ToArray();
if (_Transaction != null)
{
_Transaction.Begin();
base.Send(CompressedData, _Transaction);
_Transaction.Commit();
}
else
{
base.Send(CompressedData);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Here is the message contents for a test message. It ends up as an XML document that wraps the encoded binary data.:<?xml version="1.0"?>..<base64Binary>H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Ih63edMefTsvy2rv8V3+4/8ByygBlxMAAAA=</base64Binary>
Here is the decompression code it uses:
String Data;
//Get message and format XML
System.Messaging.Message m = MessagesList[ListIndex].Tag;
m.Formatter = new XmlMessageFormatter(new Type[]
{
typeof(string), // Send raw plain strings
typeof(byte[]), // Array of binary data
typeof(XmlNode) // Xml document
});
m.BodyStream.Position = 0;
Data = m.Body.ToString();
if (m.Body.GetType() == typeof(byte[]))
{
try
{
// The message body is an array of binary data.
// Assume it is a GZIP stream of compressed data.
byte[] CompressedData = (byte[])m.Body;
byte[] UncompressedData = null;
// Decompress it.
MemoryStream s = new MemoryStream(CompressedData);
using (GZipStream z = new GZipStream(s, CompressionMode.Decompress))
{
UncompressedData = MyExtensions.ReadRemainingBytes(z);
}
// Turn the bytes back into a string.
Data = Encoding.UTF8.GetString(UncompressedData);
}
catch
{
Data = "Unknown binary data: " +
BitConverter.ToString((byte[])m.Body, 0);
}
}
if (m.Body.GetType() == typeof(XmlElement))
{
XmlElement el = (XmlElement)m.Body;
if (el.Name == "string")
Data = el.InnerText;
else
Data = el.OuterXml;
}
I would like to point out that I am setting the Formatter of the message, which is the first step to getting the body to automatically "box" and "unbox" in the queue.
In Windows XP, m.Body.GetType() == byte[], like expected. But, in Windows 7, m.Body.GetType() == XmlElement, i.e. the wrapper XML. It no longer "unboxes" the message.
Do we need to do something differently? We have worked around it once for sending strings, as you can see at the end of the receive function, but I would like to find a real answer for why this code behaves differently on Windows 7.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果要发送字节数组,请使用 Message.BodyStream 属性:
Use the Message.BodyStream property if you want to send an array of bytes:
使用
Message.BodyStream
属性发送和接收消息,看下面的代码,您可以使用它发送和接收byte[]
。Use
Message.BodyStream
property for sending and receiving message, take a look at code below you can send and receivebyte[]
using it.