Is `NetworkStream` buffered internal?

76 Views Asked by At

I'm thinking whether it's necessary to wrap the NetworkStream in a BufferedStream for continuously read such as 1 byte, 2 bytes, 4 bytes, etc... I'm worried that calling ReadXxxAsync continuously will cause multiple unnecessary system calls or network IO.

Use case:

var stream = tcpClient.GetStream();
var buffer = new byte[4096];

await stream.ReadExactlyAsync(buffer.AsMemory(0, 1));
if (buffer[0] != ...) {
    await tcpClient.DisconnectAsync();
    return;
}

// Will this cause the 2nd time network IO operation? 
// Or only read from kernel network buffer?
await stream.ReadExactlyAsync(buffer.AsMemory(1, 2)); 
if (BinaryPrimitives.ReadUInt16BigEndian(buffer.AsSpan(1, 2)) != ...) {
    await tcpClient.DisconnectAsync();
    return;
}

// Will this cause the 3rd time network IO operation? 
await stream.ReadExactlyAsync(buffer.AsMemory(3, 2));
var messageBodyLength = BinaryPrimitives.ReadUInt16BigEndian(buffer.AsSpan(3, 2));

var messageBody = buffer.AsMemory(5, messageBodyLength);
await stream.ReadExactlyAsync(messageBody);

...
...
1

There are 1 best solutions below

0
On

Your reads are all from the OS buffer. You can't actually read from the network interface as the OS takes care of this and passes the data into an OS buffer for your application to read from.

It's relatively inefficient to read like this from the internal TCP buffer. However, I say relatively, because unless you are doing this on a high throughput server class system you probably won't notice it at all.

This is what the Microsoft System.IO.Pipelines library was designed to resolve.

If you really do want ultra fast throughput then use Pipeline's rather than trying to roll your own buffer library. It excels at this.