I'm new to pipe stream and tried to practice. I've written the following two projects and I can't see the result (which I wrote within the server project) from the client project. Here's the first project:
using (NamedPipeServerStream namedPipeServer = new NamedPipeServerStream("test-pipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message))
{
byte[] bytes = Encoding.Default.GetBytes("Hello, it's me!\n");
namedPipeServer.WaitForConnection();
Console.WriteLine("A client has connected!");
namedPipeServer.Write(bytes, 0, bytes.Length);
}
Here's the second project:
using (NamedPipeClientStream namedPipeClient = new NamedPipeClientStream(".", "test-pipe", PipeDirection.InOut))
{
namedPipeClient.Connect();
namedPipeClient.ReadMode = PipeTransmissionMode.Message;
string serverResponse = string.Empty;
byte[] readBytes = new byte[5];
while (!namedPipeClient.IsMessageComplete)
{
namedPipeClient.Read(readBytes, 0, readBytes.Length);
serverResponse = Encoding.Default.GetString(readBytes);
readBytes = new byte[5];
}
System.Console.WriteLine(serverResponse);
byte[] writeBytes = Encoding.Default.GetBytes("Hello from client!\n");
namedPipeClient.Write(writeBytes, 0, writeBytes.Length);
}
What's wrong with this?
Thanks
The client doesn't receive any message from the server, because
namedPipeClient.IsMessageComplete
must be called after read operation. See PipeStream.IsMessageComplete on docs:Otherwise
namedPipeClient.IsMessageComplete
returnstrue
and code insidewhile
-loop is not executed. So you have to rewritewhile
loop todo-while
loop to ensure, that read operation occurs beforenamedPipeClient.IsMessageComplete
is tested.But there are more problems, see comments for explanations:
EDIT:
When named pipe is in the
PipeTransmissionMode.Message
mode, every call ofNamedPipeServerStream.Write()
on the server sends data through the pipe as an individual message. Client can then receive these messages separated from each other (as opposed toPipeTransmissionMode.Byte
mode, where client receives just single continuous stream of bytes, no matter how many writes server performed usingNamedPipeServerStream.Write()
).When client reads data from pipe (
namedPipeClient.Read()
), method is allowed to return less data then requested (for example when there is not enough space in the receiving buffer to store the whole message, or message is shorter then the requested number of bytes), see docs.You can then use
namedPipeClient.IsMessageComplete
andreadCount
to detect this. Let me explain it on some example: Imagine that server sends messageABCDEFGHIJKL
to the client, encoded to byte array as{ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76 }
. This message has length of 12 bytes, thus it does not fit to your receiving buffer (readBytes
) which is 5 bytes long. So when client reads from pipe for the first time usingnamedPipeClient.Read()
, receiving buffer will contain just first 5 bytes ({ 65, 66, 67, 68, 69 }
corresponding toABCDE
) of the message. And this is wherenamedPipeClient.IsMessageComplete
will help us, because it will returnfalse
indicating that we didn't receive complete message, there are still some bytes left and we should continue reading.The second read from the pipe will be similar, we will read second part of the message (
{ 70, 71, 72, 73, 74 }
corresponding toFGHIJ
),namedPipeClient.IsMessageComplete
is stillfalse
indicating incomplete message.When third read from the pipe comletes, only 2 remaining bytes (
{ 75, 76 }
corresponding toKL
) will be read, but our buffer is still 5 bytes long, so it will look like this: ({ 75, 76, 72, 73, 74 }
corresponding toKLHIJ
). Values72, 73, 74
are still there from previous iteration of the loop. And now it is important to store value returned fromnamedPipeClient.Read()
to thereadCount
variable. It will contain value 2, indicating that only 2 bytes of thebytesRead
buffer are valid and the remaining bytes should be ignored.