Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Length of Data Available in NetworkStream

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.

like image 509
Jordan LaPrise Avatar asked Oct 15 '13 18:10

Jordan LaPrise


3 Answers

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)

like image 190
Tim S. Avatar answered Nov 11 '22 00:11

Tim S.


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.

like image 38
William Avatar answered Nov 11 '22 01:11

William


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.

like image 2
aL3891 Avatar answered Nov 10 '22 23:11

aL3891