2015-07-20 56 views
0

我正在使用命名管道在我正在進行的項目中,雙方都用C#(客戶機和服務器)編寫,並且兩者都在同一臺計算機上(命名管道用於RPC)。兩側的命名管道設置爲使用'PipeTransmissionMode.Message'模式,根據我的理解,應該將每個數據塊「打包」到一個單獨的消息中的pipe.Write()和另一端的pipe.Read()應該收到全部信息或者不收到全部信息。C#在消息模式下命名管道有時會合並消息?

在試圖反序列化接收端的數據時,我看到我獲得了大量的數據,比我發送的數據包大。於是我做了一個小測試,我創建了兩個應用程序,服務器和客戶端,它看起來像這樣:

服務器:

class Program 
{ 
    static void Main(string[] args) 
    { 
     NamedPipeServerStream pipe = new NamedPipeServerStream("TestPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous, 1024, 1024); 
     pipe.WaitForConnection(); 

     Random random = new Random(); 

     while(true) 
     { 
      byte[] buffer = new byte[32]; 
      random.NextBytes(buffer); 
      pipe.Write(buffer, 0, buffer.Length); 
      Console.WriteLine(buffer.Length); 
     } 
    } 
} 

客戶:

class Program 
{ 
    static void Main(string[] args) 
    { 
     NamedPipeClientStream pipe = new NamedPipeClientStream(".", "TestPipe", PipeDirection.InOut, PipeOptions.Asynchronous); 
     pipe.Connect(); 

     while(true) 
     { 
      byte[] buffer = new byte[2048]; 
      int read = pipe.Read(buffer, 0, buffer.Length); 
      Console.WriteLine(read); 

      if(read > 32) 
       Console.WriteLine("Big"); 
     } 
    } 
} 

運行此,服務器只輸出32(這是我的預期),但客戶端,有時輸出64,其次是「大」。這是怎麼回事?

PS:如果我把Thread.Sleep(100)在服務器上環,它工作正常(只有32個寫在兩面)

編輯: 如果我把在客戶端服務器上的Thread.Sleep(100)Thread.Sleep(200),我收到更大的數據包更頻繁,這導致我相信,如果在讀取調用之前有多條消息到達,那麼讀取將返回所有這些消息。我怎樣才能確保每次閱讀只會返回一條消息?

+0

您不應該將'ReadMode'設置爲'Message'嗎?此外,您還需要在客戶端流上設置 - 默認情況下,它處於「字節」模式。 – Luaan

+0

@Luaan'NamedPipeClientStream'的構造函數沒有接受'PipeTransmissionMode'的重載,我還沒有找到創建後設置它的方法。 – UnTraDe

+0

'ReadMode'有一個setter - 它應該在創建(或連接)管道後設置。 – Luaan

回答

0

你忘了設置ReadModeMessage還有:

pipe.ReadMode = PipeTransmissionMode.Message; 

當您創建或連接到一個管道,默認模式總是Byte,無論TransmissionMode設置。