I'm using a NamedPipeStream, client and server, I'm sending data from client to server, the data is a serialize object which include binary data.
When the server side receive the data, it always have MAX 1024 size while client send much more!! so when try to serialize the data, this cause the following exception: "Unterminated string. Expected delimiter: ". Path 'Data', line 1, position 1024."
the server buffer size defined as:
protected const int BUFFER_SIZE = 4096*4;
var stream = new NamedPipeServerStream(PipeName,
PipeDirection.InOut,
1,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous,
BUFFER_SIZE,
BUFFER_SIZE,
pipeSecurity);
stream.ReadMode = PipeTransmissionMode.Message;
I'm using :
/// <summary>
/// StreamWriter for writing messages to the pipe.
/// </summary>
protected StreamWriter PipeWriter { get; set; }
The read function:
/// <summary>
/// Reads a message from the pipe.
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
protected static byte[] ReadMessage(PipeStream stream)
{
MemoryStream memoryStream = new MemoryStream();
byte[] buffer = new byte[BUFFER_SIZE];
try
{
do
{
if (stream != null)
{
memoryStream.Write(buffer, 0, stream.Read(buffer, 0, buffer.Length));
}
} while ((m_stopRequested != false) && (stream != null) && (stream.IsMessageComplete == false));
}
catch
{
return null;
}
return memoryStream.ToArray();
}
protected override void ReadFromPipe(object state)
{
//int i = 0;
try
{
while (Pipe != null && m_stopRequested == false)
{
PipeConnectedSignal.Reset();
if (Pipe.IsConnected == false)
{//Pipe.WaitForConnection();
var asyncResult = Pipe.BeginWaitForConnection(PipeConnected, this);
if (asyncResult.AsyncWaitHandle.WaitOne(5000))
{
if (Pipe != null)
{
Pipe.EndWaitForConnection(asyncResult);
// ...
//success;
}
}
else
{
continue;
}
}
if (Pipe != null && Pipe.CanRead)
{
byte[] msg = ReadMessage(Pipe);
if (msg != null)
{
ThrowOnReceivedMessage(msg);
}
}
}
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine(" PipeName.ReadFromPipe Ex:" + ex.Message);
}
}
I don't see in the client side where I can define or change the buffer size!
Any idea?!
The basic problem is that you didn't read enough. You need to repeat the read operation if
PipeStream.IsMessageComplete
is false, and keep doing that until it returns true - that tells you the whole message has been read. Depending on your deserializer, you might need to store the data in a buffer of your own, or create some wrapper stream to handle this for you.A simple example of how this could work for simple string deserialization:
Just as a side-note - I can easily read or write as much data as I want at once - the limiting factor is the buffer I use, not the one the pipes use; although I'm using a local named pipe, it might be different for a TCP pipe (though it'd be a bit annoying - it's supposed to be abstracted away from you).
EDIT:
Okay, now it's finally obvious what your problem is. You can't use a
StreamWriter
- when sending a message long enough, it will result in multipleWrite
calls on the pipe stream, resulting in multiple separate message for your data. If you want the whole message as a single message, you must use a singleWrite
call. For example:The 1024-long buffer is
StreamWriter
s, it has nothing to do with the named pipes. UsingStreamWriter
/StreamReader
is a bad idea in any networking scenario, even when working with raw TCP streams. It just isn't what it's designed for.