消息模式下的C#命名管道有时合并消息?

时间:2015-07-20 07:40:22

标签: c# ipc rpc named-pipes

我在我正在进行的项目中使用命名管道,双方都是用C#编写的(客户端和服务器),两者都在同一台计算机上(命名管道用于RPC)。两侧的命名管道都设置为使用' PipeTransmissionMode.Message'模式根据我的理解应该" pack"在单个消息中传递给pipe.Write()的每个数据块和另一端的pipe.Read()应该接收整个消息,或者不接收任何消息。

在尝试反序列化接收端的数据时,我发现我获得了大量数据,比我发送的数据包大。所以我做了一个小测试,我创建了两个应用程序,服务器和客户端,看起来像这样:

服务器:

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后跟" Big"。发生了什么事?

P.S:如果我将Thread.Sleep(100)放在服务器循环上,它会按预期工作(双方只写32)

编辑: 如果我在服务器上放置Thread.Sleep(100)并在客户端放置Thread.Sleep(200),我会更频繁地收到更大的数据包,这使我相信如果在调用read之前到达了多个消息,则read返回他们都是。如何确保每次读取只返回一条消息?

1 个答案:

答案 0 :(得分:3)

您忘了将ReadMode设置为Message

pipe.ReadMode = PipeTransmissionMode.Message;

创建或连接管道时,无论Byte设置如何,默认模式始终为TransmissionMode