代码之家  ›  专栏  ›  技术社区  ›  dlras2

为什么msmq不发送空格字符?

  •  1
  • dlras2  · 技术社区  · 15 年前

    我正在探索msmq服务,我编写了一个简单的控制台客户机服务器应用程序,将客户机的每一个按键发送到服务器。每当击中一个控制字符( DEL , ESC , INS 等)服务器抛出错误是可以理解的。但是,每当我键入空格字符时,服务器会接收数据包,但不会抛出错误,也不会显示空格。

    服务器:

    namespace QIM
    {
        class Program
        {
            const string QUEUE = @".\Private$\qim";
            static MessageQueue _mq;
            static readonly object _mqLock = new object();
            static XmlSerializer xs;
    
            static void Main(string[] args)
            {
                lock (_mqLock)
                {
                    if (!MessageQueue.Exists(QUEUE))
                        _mq = MessageQueue.Create(QUEUE);
                    else
                        _mq = new MessageQueue(QUEUE);
                }
                xs = new XmlSerializer(typeof(string));
                _mq.BeginReceive(new TimeSpan(0, 1, 0), new object(), OnReceive);
                while (Console.ReadKey().Key != ConsoleKey.Escape) { }
            }
    
            static void OnReceive(IAsyncResult result)
            {
                Message msg;
                lock (_mqLock)
                {
                    try
                    {
                        msg = _mq.EndReceive(result);
                        Console.Write(".");
                        Console.Write(xs.Deserialize(msg.BodyStream));
                    }
                    catch (Exception ex)
                    {
                        Console.Write(ex);
                    }
                }
                _mq.BeginReceive(new TimeSpan(0, 1, 0), new object(), OnReceive);
            }
        }
    }
    

    客户:

    namespace QIM_Client
    {
        class Program
        {
            const string QUEUE = @".\Private$\qim";
            static MessageQueue _mq;
    
            static void Main(string[] args)
            {
                if (!MessageQueue.Exists(QUEUE))
                    _mq = MessageQueue.Create(QUEUE);
                else
                    _mq = new MessageQueue(QUEUE);
                ConsoleKeyInfo key = new ConsoleKeyInfo();
                while (key.Key != ConsoleKey.Escape)
                {
                    key = Console.ReadKey();
                    _mq.Send(key.KeyChar.ToString());
                }
            }
        }
    }
    

    客户端输入:

    测试,测试…

    服务器输出:

    .T.E.S.T.I.N.G.,.T.E.S.T.I.N.G.…

    您会注意到空格字符发送了一条消息,但不会显示该字符。

    2 回复  |  直到 11 年前
        1
  •  5
  •   zero323 little_kid_pea    11 年前

    您的问题不在msmq上,而是在 XmlSerializer 班级。见:

    var key = Console.ReadKey();
    
    XmlSerializer s = new XmlSerializer(typeof(string));
    
    using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
    {
        s.Serialize(ms, key.KeyChar.ToString());
    
        ms.Position = 0;
    
        var foo = (string)s.Deserialize(ms);
    }
    

    如果您在控制台中键入一个空格,您将看到 key.KeyChar.ToString() 产量 " " 但是 foo 等于 "" . 因为默认实现 XmlReader , the XML串行化器 类将只包含空格的字符串视为空;如果该字符串包含任何其他字符,则保留前导空格和尾随空格。空白区 序列化,但反序列化会将其转换为空字符串。

    改为使用:

    Console.Write(
        s.Deserialize(System.Xml.XmlReader.Create(msg.BodyStream, 
                                              new System.Xml.XmlReaderSettings() 
                                              { 
                                                  IgnoreWhitespace = false 
                                              })));
    
        2
  •  3
  •   Erv Walter    15 年前

    @adam的回答是对的。最简单的解决方案是使用BinaryMessageFormatter(它无论如何都会导致较小的消息)。

    在客户端和服务器中初始化消息队列对象之后,显式设置格式化程序:

    _mq.Formatter = new BinaryMessageFormatter();
    

    在服务器中,不要试图直接与bodystream混淆。相反,只需使用body(格式化程序已经对其进行了反序列化):

    Console.Write(".");
    Console.Write(msg.Body);