I start learning to work with socket recently. The behaviour I see in documentation is that when reading stream with a buffer, it return zero to indicate reader reached end of stream.
private static async Task ProcessStreamAsync(NetworkStream stream)
{
while (true)
{
var buffer = new Byte[64];
var received = await stream.ReadAsync(buffer);
Console.WriteLine($"Count:{received}");
var message = Encoding.UTF8.GetString(buffer, 0, received);
Console.WriteLine(message);
if (received == 0) break; // This line does not reach ever in my case!
}
}
But it is not the case I see in my code. In the last reading loop, it returns a buffer which is not full and then wait infinitely. I try to handle it with comparing buffer length and buffer capacity.
private static async Task ProcessStreamAsync(NetworkStream stream)
{
while (true)
{
var buffer = new Byte[64];
var received = await stream.ReadAsync(buffer);
Console.WriteLine($"Count:{received}");
var message = Encoding.UTF8.GetString(buffer, 0, received);
Console.WriteLine(message);
// if (received == 0) break;
if (received < buffer.Length) { break; }
}
}
but this is not possible in case of using PipeReader which allocates buffer automatically and buffer size is not available in APIs.
private static async Task ProcessWithPipes(NetworkStream stream)
{
var reader = PipeReader.Create(stream);
var writer = PipeWriter.Create(stream);
try
{
bool completed = false;
do
{
var result = await reader.ReadAsync();
if (result.Buffer.Length == 0)
{
completed = true;
Console.WriteLine("Receive Empty Buffer, Client Closed");
}
var buffer = result.Buffer;
if (buffer.IsSingleSegment)
{
string message = Encoding.UTF8.GetString(buffer);
Console.WriteLine(message);
}
else
{
foreach (var item in buffer)
{
string message = Encoding.UTF8.GetString(item.Span);
Console.WriteLine(message);
}
}
if (result.IsCompleted)
{
completed = true;
Console.WriteLine("Stream Reading Completed, Client Closed");
}
var nextPosition = buffer.GetPosition(buffer.Length);
reader.AdvanceTo(nextPosition);
} while (!completed);
await reader.CompleteAsync();
}
catch (System.Exception)
{
throw;
}
}
}
By the way I am using linux ubuntu for my development. Is this a normal behaviour?
2
Answers
After reading responses and comments, I found two way for solving this: 1- Use underlying network stream
DataAvailable
property instead of ReadResultIsCompleted
orBuffer.Length==0
to break the while loop as below:2- Use PipeWriter to fill pipe with network stream and then use PipeReader to read it
I think changing the method you use will also solve your problem. You can get healthier results by using the method I shared the link of. I will be glad if you inform me about the result.
Try This;
https://stackoverflow.com/a/26059057/12645793