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

消息模式下的C#命名管道有时会合并消息?,c#,ipc,rpc,named-pipes,C#,Ipc,Rpc,Named Pipes,我在一个项目中使用命名管道,双方都用C#(客户端和服务器)编写,并且都在同一台计算机上(命名管道用于RPC)。两侧的命名管道都设置为使用“PipeTransmissionMode.Message”模式,根据我的理解,该模式应将传递给pipe.Write()的每个数据块“打包”到单个消息中,而另一端的pipe.Read()应接收整个消息或不接收任何消息 在尝试对接收端的数据进行反序列化时,我发现我得到的数据量很大,比我发送的数据包还要大。所以我做了一个小测试,创建了两个应用程序,服务器和客户端,如

我在一个项目中使用命名管道,双方都用C#(客户端和服务器)编写,并且都在同一台计算机上(命名管道用于RPC)。两侧的命名管道都设置为使用“PipeTransmissionMode.Message”模式,根据我的理解,该模式应将传递给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”。发生什么事了

附言:如果我在服务器循环中放置
Thread.Sleep(100)
,它会像预期的那样工作(两边只写32个)

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

您忘记将
读取模式设置为
消息

pipe.ReadMode = PipeTransmissionMode.Message;

创建或连接到管道时,默认模式始终为
字节
,无论
传输模式
设置如何。

是否也应将
读取模式
设置为
消息
?此外,您还需要在客户端流上设置这两个参数-默认情况下,它处于
Byte
模式。@Luaan
NamedPipeClientStream
的构造函数没有重载,接受
PipeTransmissionMode
,我还没有找到在创建之后设置它的方法。
ReadMode
有一个setter-应该在创建(或连接到)管道之后设置它。@Luaan Nice,这似乎解决了问题!我还发现在阅读时需要使用
NamedPipeClientStream.IsMessageComplete
,以确保您拥有所有信息。你能给我一个答案让我接受吗?