2010-05-24 4 views
1

MSMQ 서비스를 탐색 중이며 각 클라이언트의 키 입력을 서버로 보내는 간단한 콘솔 클라이언트 - 서버 응용 프로그램을 작성했습니다. 제어 문자 (DEL, ESC, INS 등)를 치면 서버가 당연히 오류를 던집니다. 그러나 공백 문자를 입력 할 때마다 서버는 패킷을 받지만 오류는 발생시키지 않으며 공백을 표시하지 않습니다.MSMQ에서 공백 문자를 보내지 않는 이유는 무엇입니까?

서버 :

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()); 
      } 
     } 
    } 
} 

클라이언트 입력 :

테스트, 테스트 ...

서버 출력 :

.Testing .. 테스트 .....

당신은, 공백 문자 메시지를 보내는 것을 알 수 있지만 문자 ISN ' 표시됩니다.

+0

제안 : 예외적으로 식사를 중단하십시오. 빈 catch 블록을 없애고 어떤 예외가 던져지고 있는지 확인할 수 있습니다. –

+0

전화하세요. 공백 문자는 예외를 보내지 않습니다. 'BeginReceive' 타임 아웃과'MessageQueueExceptions'와'XmlExceptions'를 각각 보내는 제어 문자들. – dlras2

+0

완벽한 예외 사항을 게시 하시겠습니까? –

답변

5

문제는 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의 기본 구현으로 인해 XmlSerializer 클래스는 공백 만 포함 된 문자열을 비어있는 것으로 간주합니다. 캐릭터 라인에 다른 문자가 포함되어있는 경우, 선두와 말미의 스페이스가 보존됩니다. 공백 문자 이 직렬화 되나이를 비 직렬화하면 빈 문자열이됩니다.

사용이 대신은 :

Console.Write(
    s.Deserialize(System.Xml.XmlReader.Create(msg.BodyStream, 
              new System.Xml.XmlReaderSettings() 
              { 
               IgnoreWhitespace = false 
              }))); 
3

@ 아담의 대답은 권리입니다. 가장 쉬운 해결책은 BinaryMessageFormatter를 사용하는 것입니다 (결과적으로 메시지가 약간 작아짐).

클라이언트와 서버 모두에서 메시지 큐 개체를 초기화 한 후, 명시 적으로 포맷을 설정

_mq.Formatter = new BinaryMessageFormatter(); 

그런 다음 서버에 직접 BodyStream 엉망으로하지 않습니다. 대신 본체 만 사용하십시오 (포맷터에서 이미 deserialize되어 있음).

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

+1. 내 현재 프로젝트에서'BinaryMessageFormatter'을 사용하지만, OP의 솔루션을 XML로 유지할 것이라고 생각했습니다. –

+0

+1,'BinaryMessageFormatter'을 제안했습니다. – dlras2

+0

또한, BinaryMessageFormatter는 제어 문자에 대한 예외를 발생시키지 않습니다. – dlras2

관련 문제