Question

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.

Was it helpful?

Solution

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)

OTHER TIPS

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.

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.

You could send the lenght of the incoming data first. For example: You have data = byte[16] you want to send. So at first you send the 16 and define on the server, that this length is always 2 (because 16 has two characters). Now you know that the incomingLength = 16. You can wait now for data of the lenght incomingLength.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top