MSMQ + C#,接收带有编码的 byte[] 正文的消息在 Windows 7 和 Windows XP 上的行为不同

发布于 2024-11-04 10:36:56 字数 3501 浏览 0 评论 0原文

我有一个显示 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 文档封装了编码的二进制数据: <代码>..H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcplVmVdZhZA zO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Ih63edMefTsvy2rv8V3+4/8ByygBlxMAAAA=


下面是它使用的解压代码:

        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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

っ左 2024-11-11 10:36:56

如果要发送字节数组,请使用 Message.BodyStream 属性:

System.Messaging.MessageQueue queue = new MessageQueue(queueFormatName, false, true, QueueAccessMode.Send);

System.Messaging.Message msg = new System.Messaging.Message();
msg.BodyStream = new MemoryStream(buffer);

queue.Send(msg, MessageQueueTransactionType.Single);

Use the Message.BodyStream property if you want to send an array of bytes:

System.Messaging.MessageQueue queue = new MessageQueue(queueFormatName, false, true, QueueAccessMode.Send);

System.Messaging.Message msg = new System.Messaging.Message();
msg.BodyStream = new MemoryStream(buffer);

queue.Send(msg, MessageQueueTransactionType.Single);
一城柳絮吹成雪 2024-11-11 10:36:56

使用 Message.BodyStream 属性发送和接收消息,看下面的代码,您可以使用它发送和接收 byte[]

public void SendMessage()
{
    MessageQueue myQueue = new MessageQueue(".\\QUEUE");
    byte[] msg = new byte[2];
    msg[0] = 29;               
    // Send the array to the queue.
    Message msg1 = new Message();
    msg1.BodyStream = new MemoryStream(msg);
    messageQueue.Send(msg1);                
}

public void ReceiveMessage()
{
    MessageQueue myQueue = new MessageQueue(".\\QUEUE");               
    Message myMessage =myQueue.Receive();
    byte[] msg = ReadFully(myMessage.BodyStream);
}

public static byte[] ReadFully(Stream input)
{
    byte[] buffer = new byte[16 * 1024];
    using (MemoryStream ms = new MemoryStream())
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, read);
        }
        return ms.ToArray();
    }
}

Use Message.BodyStream property for sending and receiving message, take a look at code below you can send and receive byte[] using it.

public void SendMessage()
{
    MessageQueue myQueue = new MessageQueue(".\\QUEUE");
    byte[] msg = new byte[2];
    msg[0] = 29;               
    // Send the array to the queue.
    Message msg1 = new Message();
    msg1.BodyStream = new MemoryStream(msg);
    messageQueue.Send(msg1);                
}

public void ReceiveMessage()
{
    MessageQueue myQueue = new MessageQueue(".\\QUEUE");               
    Message myMessage =myQueue.Receive();
    byte[] msg = ReadFully(myMessage.BodyStream);
}

public static byte[] ReadFully(Stream input)
{
    byte[] buffer = new byte[16 * 1024];
    using (MemoryStream ms = new MemoryStream())
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, read);
        }
        return ms.ToArray();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文