Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Named Pipes in message mode sometimes merge messages?

I'm using Named Pipes in a project I'm working on, both sides are written in C# (client and server) and both are on the same computer (The named pipes are used for RPC). The named pipes on both sides are set to use 'PipeTransmissionMode.Message' mode which according to my understanding should "pack" each chunk of data passed to pipe.Write() in a single message and pipe.Read() on the other end should receive the entire message or none of it.

While trying to deserialize the data on the receiving end, I saw that I get big chucks of data, bigger than the packets I sent. So I made a small test, I created two Applications, server and client, which looks like this:

Server:

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

Client:

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

Running this, the server outputs only 32 (which is what I expected) but the client, sometimes output 64 followed by "Big". What's going on?

P.S: If I put Thread.Sleep(100) on the server loop, it works as expected (writes only 32 on both sides)

EDIT: If I put a Thread.Sleep(100) on the server and Thread.Sleep(200) on the client, I receive bigger packets more often, which leads me to believe that if more than one message is arrived before the call to read then read returns all of them. How can I ensure each read will return only one message?

like image 655
UnTraDe Avatar asked Sep 08 '25 03:09

UnTraDe


1 Answers

You forgot to set the ReadMode to Message as well:

pipe.ReadMode = PipeTransmissionMode.Message;

When you create or connect to a pipe, the default mode is always Byte, regardless of the TransmissionMode setting.

like image 135
Luaan Avatar answered Sep 10 '25 09:09

Luaan