How to determine when there is no more data to read in NetworkStream?

I have a web application that connects to a server using a TCP connection and reads a binary document, which then writes to its response object. In other words, it transfers the file from an external server using a custom protocol and returns this file to the client via HTTP.

The server sends the status code and type mime, which I read successfully, and then writes the contents of the file and closes the socket. This seems to be normal.

The client (C # web application) reads the data:

     private NetworkStream stream_;

     public void WriteDocument(HttpResponse response)
     {
        while (stream_.DataAvailable)
        {
           const int bufsize = 4 * 1024;
           byte[] buffer = new byte[bufsize];
           int nbytes = stream_.Read(buffer, 0, bufsize);
           if (nbytes > 0)
           {
              if (nbytes < bufsize)
                 Array.Resize<byte>(ref buffer, nbytes);
              response.BinaryWrite(buffer);
           }
        }
        response.End();
     }

It seems to always exit the read cycle before all data is received. What am I doing wrong?

+3
source share
4 answers

OutputStream . Stream Flush.

    public void WriteDocument(HttpResponse response) {
        StreamCopy(response.OutputStream, stream_);
        response.End();
    }

    public static void StreamCopy(Stream dest, Stream src) {
        byte[] buffer = new byte[4 * 1024];
        int n = 1;
        while (n > 0) {
            n = src.Read(buffer, 0, buffer.Length);
            dest.Write(buffer, 0, n);
        }
        dest.Flush();
    }
+3

. , . , , .

DataAvailable , NOW, ( ) , . , , stream_.Socket.Connected && stream_.Socket.Readable

    public static byte[] doFetchBinaryUrl(string url)
    {
        BinaryReader rdr;
        HttpWebResponse res;
        try
        {
            res = fetch(url);
            rdr = new BinaryReader(res.GetResponseStream());
        }
        catch (NullReferenceException nre)
        {
            return new byte[] { };
        }
        int len = int.Parse(res.GetResponseHeader("Content-Length"));
        byte[] rv = new byte[len];
        for (int i = 0; i < len - 1; i++)
        {
            rv[i] = rdr.ReadByte();
        }
        res.Close();
        return rv;
    }
+2

, .Net, , Read(), 0 , . , - :

char buffer[4096];
int num_read;

while ( num_read = src.Read(sizeof(buffer)) > 0 )
{
   dst.Write(buffer, num_read);
}
+1
source

The root of your problem is the line:

while (stream_.DataAvailable)

DataAvailable simply means that the data in the stream buffer is ready to be read and processed. This does not guarantee that the "end" of the flow achieved. In particular, DataAvailable can be false if there is any pause in the transmission or if your sender is slower than your reader.

+1
source

Source: https://habr.com/ru/post/1697294/


All Articles