Search code examples
c#streamreadernamed-pipesstreamwriter

Sending a multiline string over NamedPipe?


How can I send a multiline string with blank lines over a NamedPipe?

If I send a string

string text= @"line 1 
line2

line four
";
StreamWriter sw = new StreamWriter(client);
sw.Write(text);

I get on the server side only "line 1":

StreamReader sr = new StreamReader(server);
string message = sr.ReadLine();

When I try something like this

StringBuilder message = new StringBuilder();
string line;
while ((line = sr.ReadLine()) != null)
{
    message.Append(line + Environment.NewLine);
}

It hangs in the loop while the client is connected and only releases when the client disconnects.

Any ideas how I can get the whole string without hanging in this loop? I need to to process the string and return it on the same way to the client.

It's important that I keep the original formatting of the string including blank lines and whitespace.


Solution

  • StreamReader is a line-oriented reader. It will read the first line (terminated by a newline). If you want the rest of the text, you have to issue multiple readlines. That is:

    StreamReader sr = new StreamReader(server);
    string message = sr.ReadLine(); // will get "line1"
    string message2 = sr.ReadLine(); // will get "line2"
    

    You don't want to "read to end" on a network stream, because that's going to hang the reader until the server closes the connection. That might be a very long time and could overflow a buffer.

    Typically, you'll see this:

    NetworkStream stream = CreateNetworkStream(); // however you're creating the stream
    using (StreamReader reader = new StreamReader(stream))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            // process line received from stream
        }
    }
    

    That gives you each line as it's received, and will terminate when the server closes the stream.

    If you want the reader to process the entire multi-line string as a single entity, you can't reliably do it with StreamReader. You'll probably want to use a BinaryWriter on the server and a BinaryReader on the client.