Get Length of Data Available in NetworkStream

21,453

Solution 1

When accessing Streams, you usually read and write data in small chunks (e.g. a kilobyte or so), or use a method like CopyTo that does that for you.

This is an example using CopyTo to copy the contents of a stream to another stream and return it as a byte[] from a method, using an automatically-sized buffer.

using (MemoryStream ms = new MemoryStream())
{
    networkStream.CopyTo(ms);
    return ms.ToArray();
}

This is code that reads data in the same way, but more manually, which might be better for you to work with, depending on what you're doing with the data:

byte[] buffer = new byte[2048]; // read in chunks of 2KB
int bytesRead;
while((bytesRead = networkStream.Read(buffer, 0, buffer.Length)) > 0)
{
    //do something with data in buffer, up to the size indicated by bytesRead
}

(the basis for these code snippets came from Most efficient way of reading data from a stream)

Solution 2

There is no inherent length of a network stream. You will either have to send the length of the data to follow from the other end or read all of the incoming data into a different stream where you can access the length information.

Solution 3

The thing is, you can't really be sure all the data is read by the socket yet, more data might come in at any time. This is try even if you somehow do know how much data to expect, say if you have a package header that contains the length. the whole packet might not be received yet.

If you're reading arbitrary data (like a file perhaps) you should have a buffer of reasonable size (like 1k-10k or whatever you find to be optimal for your scenario) and then write the data to a file as its read from the stream.

var buffer = byte[1000];
var readBytes = 0;
using(var netstream = GetTheStreamSomhow()){
    using(var fileStream = (GetFileStreamSomeHow())){
        while(netstream.Socket.Connected) //determine if there is more data, here we read until the socket is closed
        {
            readBytes = netstream.Read(buffer,0,buffer.Length);
            fileStrem.Write(buffer,0,buffer.Length);
        }
    }
}

Or just use CopyTo like Tim suggested :) Just make sure that all the data has indeed been read, including data that hasn't gotten across the network yet.

Share:
21,453
Jordan LaPrise
Author by

Jordan LaPrise

I am a 16 year old programming and computer enthusiast, I have been programming ever since I had my hands on a computer, I release everything under the name "CalcuProcessing" which currently focuses on equipping beginning programmers with the tools they need to develop professional quality software.

Updated on November 04, 2020

Comments

  • Jordan LaPrise
    Jordan LaPrise over 3 years

    I would like to be able to get the length of the data available from a TCP network stream in C# to set the size of the buffer before reading from the network stream. There is a NetworkStream.Length property but it isn't implemented yet, and I don't want to allocate an enormous size for the buffer as it would take up too much space. The only way I though of doing it would be to precede the data transfer with another telling the size, but this seems a little messy. What would be the best way for me to go about doing this.

  • Jordan LaPrise
    Jordan LaPrise over 10 years
    This is great! I'll use this to write to a memory stream until all the data has arrived.
  • Jordan LaPrise
    Jordan LaPrise over 10 years
    I actually modified your code a bit, to make sure that I have the entire object before continuing, essentially, the first 8 bytes of the packet are the size, and it will continue reading what it can until it has the same amount of bytes in memory as it is expecting.
  • Uwe Köhler
    Uwe Köhler almost 5 years
    In many protocols the byte length of the message must be set by the sender in a message header with 1, 2 or 4 bytes