17

I'm trying to use the new HttpClient class (in .NET 4.5) to retrieve partial responses from the server in order to check the content. I need to limit the size of data retrieved to the first few bytes of content in the HTTP requests to limit the bandwidth usage.

I've been unable to accomplish this. I have tried using GetAsync(url, HttpCompletionOption.ResponseHeadersRead) then use Content.ReadAsStream() in an attempt to only read the headers and then read the response stream in a small chunk. I also tried GetStreamAsync() and then reading the Content stream with a small chunk (1000 bytes).

In both cases it appears that HttpClient is pulling and buffering the entire HTTP response rather than just reading the requested byte count from the stream.

Initially I was using Fiddler to monitor the data, but realized that Fiddler might actually be causing the entire content to be proxied. I switched to using System.Net tracing (which shows):

ConnectStream#6044116::ConnectStream(Buffered 16712 bytes.)

which is the full size rather than just the 1000 bytes read. I've also double checked in Wireshark to verify that indeed the the full content is being pulled over the wire and it is. With larger content (like a 110k link) I get about 20k of data before the TCP/IP stream is truncated.

The two ways I've tried to read the data:

response = await client.GetAsync(site.Url, HttpCompletionOption.ResponseHeadersRead);
var stream = await response.Content.ReadAsStreamAsync();

var buffer = new byte[1000];                                        
var count = await stream.ReadAsync(buffer, 0, buffer.Length);
response.Close()  // close ASAP
result.LastResponse = Encoding.UTF8.GetString(buffer);

and:

var stream = await client.GetStreamAsync(site.Url);
var buffer = new byte[1000];
var count = await stream.ReadAsync(buffer, 0, buffer.Length);
result.LastResponse = Encoding.UTF8.GetString(buffer);

Both of them produce nearly identical .NET trace's which include the buffered read.

Is it possible to have HttpClient actually read only a small chunk of an Http Repsonse, rather than the entire response in order to not use the full bandwidth? IOW is there a way to disable any buffering on the HTTP connection using either HttpClient or HttpWebRequest?

Update: After some more extensive testing it looks like both HttpClient and HttpWebRequest buffer the first few TCP/IP frames - presumably to ensure the HTTP header is captured. So if you return a small enough request, it tends to get loaded completely just because it's in that inital bufferred read. But when loading a larger content url, the content does get truncated. For HttpClient it's around 20k, for HttpWebRequest somewhere around 8k for me.

Using TcpClient doesn't have any buffering issues. When using it I get content read at the size of the read plus a bit extra for the nearest buffer size overlap, but that does include the HTTP header. Using TcpClient is not really an option for me as we have to deal with SSL, Redirects, Auth, Chunked content etc. At that point I'd be looking at implementing a full custom HTTP client just to turn of buffering.

Rick Strahl
  • 17,302
  • 14
  • 89
  • 134
  • I suspect you need to set the [HttpWebRequest.AllowReadStreamBuffering](http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.allowreadstreambuffering%28v=vs.110%29.aspx) property to `false`. Unfortunately, the relevant methods in the `HttpClientHandler` class are `internal`, so you'd need to re-implement the whole class to set this property. – Richard Deeming Jan 09 '14 at 13:21
  • Richard, I tried using a raw HttpWebRequest and setting those flags, but found that the behavior really didn't change. According to Howard Dierking on .NET 4.5 (which I'm using) when you choose non-buffering options those flags should automatically be set. Maybe they are but it's not quite having the desired effect. – Rick Strahl Jan 10 '14 at 02:57

4 Answers4

4

The best way to achive what you need to do is something like the following:

using System;
using System.Net.Sockets;

namespace tcpclienttest
{
  class Program
  {
    static byte[] GetData(string server, string pageName, int byteCount, out int     actualByteCountRecieved)
    {
      const int port = 80;
      TcpClient client = new TcpClient(server, port);

      string fullRequest = "GET " + pageName + " HTTP/1.1\nHost: " + server + "\n\n";
      byte[] outputData = System.Text.Encoding.ASCII.GetBytes(fullRequest);

      NetworkStream stream = client.GetStream();
      stream.Write(outputData, 0, outputData.Length);

      byte[] inputData = new Byte[byteCount];

      actualByteCountRecieved = stream.Read(inputData, 0, byteCount);

      // If you want the data as a string, set the function return type to a string
      // return 'responseData' rather than 'inputData'
      // and uncomment the next 2 lines
      //string responseData = String.Empty;
      //responseData = System.Text.Encoding.ASCII.GetString(inputData, 0, actualByteCountRecieved);

      stream.Close();
      client.Close();

      return inputData;
    }

    static void Main(string[] args)
    {
      int actualCount;
      const int requestedCount = 1024;
      const string server = "myserver.mydomain.com"; // NOTE: NO Http:// or https:// bit, just domain or IP
      const string page = "/folder/page.ext";

      byte[] myPartialPage = GetData(server, page, requestedCount, out actualCount);
    }
  }
}

Couple of points to note however:

There's NO error handling in there, so you might want to wrap it all in a try/catch or something to make sure you get hold of any connection errors, timeouts, unsolved IP resolution etc.

Beacuse your dealing with the raw stream, then the HTTP headers are also in there, so you'll need to take them into account.

You could in theory, put a loop in just before the main socket read, in keep grabbing data until you get a blank \n on it's own in a line, that will tell you where the headers end, then you could grab your actual count of data, but since I don't know the server your talking too I left that bit out :-)

If you copy/Paste the entire code into a new console project in VS it's runnable as it is, so you can single step it.

As far as I know the HTTP client doesn't make it's raw stream available to the user, and even then if it did because it's allocated as a streaming connection it's not likely you would have much control over it's count, I've looked into it before and given up.

I've used this code a number of times and it works well for me in similar cases, in fact I have a monitor that sits and gets stats from my WiFi adapter using it so I can see who's connecting.

Any questions, feel free to hit me up on here, or ping me on twitter my handle is @shawty_ds (just in case you lost it)

Shawty

Rick Strahl
  • 17,302
  • 14
  • 89
  • 134
shawty
  • 5,729
  • 2
  • 37
  • 71
  • PS: 1st line should read 'Hi Rick,' but SO keeps cutting it off for some reason!!! – shawty Jan 09 '14 at 11:29
  • 1
    Thanks this is nice to reference here. Unfortunately TcpClient isn't going to work for me as I'm going to have to deal with arbitrary HTTP urls. There could be SSL requests, chunked requests, Redirects, REST calls with headers, encoded content data, SOAP, Authentication etc. so there's too much other stuff to deal with at this low level. If SSL weren't an issue I might have considered it :-) – Rick Strahl Jan 09 '14 at 12:02
  • No probs Rick, yea I take your point there is a whole world of mess there. If I come across anything I'll be sure to let you know however. – shawty Jan 09 '14 at 16:00
  • @shawty HttpClient does provide direct access to the underlying network stream, no need to drop down to TcpClient. – Darrel Miller Jan 09 '14 at 17:12
  • @DarrelMiller - how do we do that? It looks like some of the HttpWebRequest options like the req.ServicePointReceiveBufferSize at least help reduce the size of buffered data that comes down. – Rick Strahl Jan 11 '14 at 02:51
  • One more note here: Using TcpClient() I can reduce the network load to just a little over the requested size. It's doing a literal read on the connection without buffering anything. I suspect the issue is that the HTTP stack is doing the initial read to capture the headers and that chunk happens to be fairly sizable... – Rick Strahl Jan 11 '14 at 03:06
  • @shawty, I am reading multipart/mixed http response where the part size is small - say around 200 bytes. I have tried HttpClient, WebRequest and finally TCPClient. I am seeing some buffering even at TCPClient - I received response only in chunk of around 1000 bytes. Any pointers, to remove or reduce this buffering as well as. – VinayC Jan 06 '15 at 14:07
  • @VinayC sorry no, as far as I'm aware using a raw connection like that shouldn't buffer anything. Not only that but it's a while since I looked at that code, I think you'll most likley find that the smallest amount of data you can capture will be equal to the MTU Size of the TCP networking software configured on the machine in question (http://en.wikipedia.org/wiki/Maximum_transmission_unit) which is generally around about 1500 bytes. Using UDP might get you less than that, but I couldn't really be sure there either. – shawty Jan 06 '15 at 14:24
  • I had the similar issue on WindowsRuntime spent some days with HttpClient, HttpWebRequest and so on and ended up with this solution. With TcpClient I can control all timeouts, cancellation, amount of data read in a way I want. – norekhov Apr 28 '15 at 04:40
1

I may be wrong at this but I think you're getting confused : when you send the request to the server, it will send you the complete answer through the network. Then it is buffered somewhere by the framework and you access it using the stream. If you don't want the remote server to send you the full answer, you may be able to specify the range of bytes you want using http headers. See HTTP Status: 206 Partial Content and Range Requests for example.

Marshall777
  • 1,196
  • 5
  • 15
  • 1
    Yeah I get the server is sending the response, but the client doesn't have to choose to read it all. Until the client socket reads the data from the server there's no network traffic :-) So if I could read the raw stream, unbuffered this would allow me to reduce the actual bytes travelling over the wire. The caching is what's screwing this up. – Rick Strahl Jan 09 '14 at 10:52
  • And just to clarify why I'm doing this crazy bit: I'm building a monitoring application that'll be checking *a lot* of arbitrary urls, but for most we'll only be interested in a very small number of bytes of each request (something like 2000 bytes max). I need to minimize the amount of data that the client consumes otherwise we'll be churning through 100's of megabytes every few minutes. – Rick Strahl Jan 09 '14 at 10:54
  • I'm just throwing this out as a guess, line of inquiry, but if the payload is under the TcpWindowSize then won't it pull the whole thing in one gulp? – Luke Puplett Jan 09 '14 at 11:15
  • I may be totally wrong, but I think its wise to use a lower-level sniffer if reducing over-the-wire data is your goal, since the buffering in high-level abstractions may not be giving the full picture. There's also chunked HTTP which might be useful if you want the server to shovel smaller data down the connection as it comes available. – Luke Puplett Jan 09 '14 at 11:41
  • Yeah chunked would work, except I have no control over the URLs that will be accessed. Lower level TCP connection could solve all this, but unfortunately SSL is an issue and implementing an SSL HTTP client isn't something I want to dabble with. Shame that this isn't supported natively in someway - I used to be able to do this with WinInet in the past. – Rick Strahl Jan 09 '14 at 12:25
  • @RickStrahl Have you also tried using HttpWebRequest ? You could then use [HttpWebResponse.GetResponseStream](http://msdn.microsoft.com/fr-fr/library/system.net.httpwebresponse.getresponsestream(v=vs.110).aspx) and read it the way you want. – Marshall777 Jan 09 '14 at 13:09
  • 1
    @Marshall777 It shouldn't make a difference, HttpClient uses HttpWebResoonse.GetResponseStream under the covers anyway (by default). It is possible to do this partial read with HttpClient. Not sure why it isn't working for Rick. – Darrel Miller Jan 09 '14 at 16:38
  • @DarrelMiller - It does make a difference though. Using HttpWebRequest the buffer is less than half that of HttpClient() and I can control the connection a bit better. You mentioned access to the underlying request - how? – Rick Strahl Jan 11 '14 at 03:04
  • @RickStrahl WHen you do GetStreamAsync the stream that comes back is a ReadOnlyStream that wraps a DelegatingStream that wraps the NetworkStream. So you are pulling bytes directly from the network stream, but you can't get access to the object instance directly. – Darrel Miller Jan 11 '14 at 17:27
1

I think/hope this may help.

How can I perform a GET request without downloading the content?

As I suspected, the underlying layers will pull more than you want despite what .NET sees.

Update

Although HttpWebRequest.AddRange(-256) will get the first 256 bytes, it seems that will only work for a static file on IIS.

It sets the Range header (not to be confused with If-Range).

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2

The server advertises it supports range requests using the Accept-Ranges header.

For Rick's problem this may be good or bad, depending on whether he needs to read static content or not. My guess is that its not what he wants.

An alternative might be to set the ReceiveBufferSize on the ServicePoint which is exposed on WebRequest.

Community
  • 1
  • 1
Luke Puplett
  • 42,091
  • 47
  • 181
  • 266
  • 1
    Yup I'm using Range but as you point out it just won't work on everything - only where the server supports it (static content or some module). My content will be arbitrary. I tried changing the req.ServicePoint.ReceiveBufferSize, but that literally had no effect - TCP/IP still seems to be buffering about 20k on the first read. – Rick Strahl Jan 11 '14 at 02:30
  • 1
    Rick seems a cheek to ask this 3 1/2 years on but.... Did you ever solve this ? :-) – Ron Weston Oct 29 '14 at 07:58
0

Here's my setup. I don't know why you are seeing the response buffered. Could it be related to the host?

 class Program
    {
        static void Main(string[] args)
        {
            var host = String.Format("http://{0}:8080/", Environment.MachineName);
            var server = CreateServer(host);

            TestBigDownload(host);

            Console.WriteLine("Done");
            server.Dispose();
        }


        private static void TestBigDownload(string host)
        {
            var httpclient = new HttpClient() { BaseAddress = new Uri(host) };
            var stream = httpclient.GetStreamAsync("bigresource").Result;

            var bytes = new byte[10000];
            var bytesread = stream.Read(bytes, 0, 1000);
        }

        private static IDisposable CreateServer(string host)
        {
            var server = WebApp.Start(host, app =>
            {
                var config = new HttpConfiguration();
                config.MapHttpAttributeRoutes();
                app.UseWebApi(config);
            });
            return server;
        }
    }




    [Route("bigresource")]
    public class BigResourceController : ApiController
    {
        public HttpResponseMessage Get()
        {
            var sb = new StringBuilder();
            for (int i = 0; i < 10000; i++)
            {
                sb.Append(i.ToString());
                sb.Append(",");
            }
            var content = new StringContent(sb.ToString());
            var response = new HttpResponseMessage()
            {
                Content = content
            };

            return response;
        }
    }

Logging config

  <system.diagnostics>
    <sources>
      <source name="System.Net">
        <listeners>
          <add name="System.Net"/>
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="System.Net" value="Verbose"/>
    </switches>
    <sharedListeners>
      <add name="System.Net"
        type="System.Diagnostics.TextWriterTraceListener"
        initializeData="network.log"
      />
    </sharedListeners>
    <trace autoflush="true"/>
  </system.diagnostics>

Resulting log

System.Net Information: 0 : [15028] Current OS installation type is 'Client'.
System.Net Verbose: 0 : [15028] HttpWebRequest#40383808::HttpWebRequest(http://oak:8080/bigresource#-236952546)
System.Net Information: 0 : [15028] RAS supported: True
System.Net Verbose: 0 : [15028] Exiting HttpWebRequest#40383808::HttpWebRequest() 
System.Net Verbose: 0 : [15028] HttpWebRequest#40383808::HttpWebRequest(uri: 'http://oak:8080/bigresource', connectionGroupName: '17480744')
System.Net Verbose: 0 : [15028] Exiting HttpWebRequest#40383808::HttpWebRequest() 
System.Net Verbose: 0 : [25748] HttpWebRequest#40383808::BeginGetResponse()
System.Net Verbose: 0 : [25748] ServicePoint#45653674::ServicePoint(127.0.0.1:8888)
System.Net Information: 0 : [25748] Associating HttpWebRequest#40383808 with ServicePoint#45653674
System.Net Information: 0 : [25748] Associating Connection#41149443 with HttpWebRequest#40383808
System.Net Verbose: 0 : [25748] Exiting HttpWebRequest#40383808::BeginGetResponse()     -> ContextAwareResult#39785641
System.Net Information: 0 : [3264] Connection#41149443 - Created connection from 127.0.0.1:10411 to 127.0.0.1:8888.
System.Net Information: 0 : [3264] Associating HttpWebRequest#40383808 with ConnectStream#39086322
System.Net Information: 0 : [3264] HttpWebRequest#40383808 - Request: GET http://oak:8080/bigresource HTTP/1.1

System.Net Information: 0 : [3264] ConnectStream#39086322 - Sending headers
{
Host: oak:8080
Proxy-Connection: Keep-Alive
}.
System.Net Information: 0 : [21384] Connection#41149443 - Received status line: Version=1.1, StatusCode=200, StatusDescription=OK.
System.Net Information: 0 : [21384] Connection#41149443 - Received headers
{
Content-Length: 48890
Content-Type: text/plain; charset=utf-8
Date: Thu, 09 Jan 2014 16:41:59 GMT
Server: Microsoft-HTTPAPI/2.0
}.
System.Net Information: 0 : [21384] ConnectStream#56140151::ConnectStream(Buffered 48890 bytes.)
System.Net Information: 0 : [21384] Associating HttpWebRequest#40383808 with ConnectStream#56140151
System.Net Information: 0 : [21384] Associating HttpWebRequest#40383808 with HttpWebResponse#1997173
System.Net Verbose: 0 : [21384] HttpWebRequest#40383808::EndGetResponse()
System.Net Verbose: 0 : [21384] Exiting HttpWebRequest#40383808::EndGetResponse()   -> HttpWebResponse#1997173
System.Net Verbose: 0 : [21384] HttpWebResponse#1997173::GetResponseStream()
System.Net Information: 0 : [21384] ContentLength=48890
System.Net Verbose: 0 : [21384] Exiting HttpWebResponse#1997173::GetResponseStream()    -> ConnectStream#56140151
System.Net Verbose: 0 : [15028] ConnectStream#56140151::Read()
System.Net Verbose: 0 : [15028] Data from ConnectStream#56140151::Read
System.Net Verbose: 0 : [15028] 00000000 : 30 2C 31 2C 32 2C 33 2C-34 2C 35 2C 36 2C 37 2C : 0,1,2,3,4,5,6,7,
System.Net Verbose: 0 : [15028] 00000010 : 38 2C 39 2C 31 30 2C 31-31 2C 31 32 2C 31 33 2C : 8,9,10,11,12,13,
System.Net Verbose: 0 : [15028] 00000020 : 31 34 2C 31 35 2C 31 36-2C 31 37 2C 31 38 2C 31 : 14,15,16,17,18,1
System.Net Verbose: 0 : [15028] 00000030 : 39 2C 32 30 2C 32 31 2C-32 32 2C 32 33 2C 32 34 : 9,20,21,22,23,24
System.Net Verbose: 0 : [15028] 00000040 : 2C 32 35 2C 32 36 2C 32-37 2C 32 38 2C 32 39 2C : ,25,26,27,28,29,
System.Net Verbose: 0 : [15028] 00000050 : 33 30 2C 33 31 2C 33 32-2C 33 33 2C 33 34 2C 33 : 30,31,32,33,34,3
System.Net Verbose: 0 : [15028] 00000060 : 35 2C 33 36 2C 33 37 2C-33 38 2C 33 39 2C 34 30 : 5,36,37,38,39,40
System.Net Verbose: 0 : [15028] 00000070 : 2C 34 31 2C 34 32 2C 34-33 2C 34 34 2C 34 35 2C : ,41,42,43,44,45,
System.Net Verbose: 0 : [15028] 00000080 : 34 36 2C 34 37 2C 34 38-2C 34 39 2C 35 30 2C 35 : 46,47,48,49,50,5
System.Net Verbose: 0 : [15028] 00000090 : 31 2C 35 32 2C 35 33 2C-35 34 2C 35 35 2C 35 36 : 1,52,53,54,55,56
System.Net Verbose: 0 : [15028] 000000A0 : 2C 35 37 2C 35 38 2C 35-39 2C 36 30 2C 36 31 2C : ,57,58,59,60,61,
System.Net Verbose: 0 : [15028] 000000B0 : 36 32 2C 36 33 2C 36 34-2C 36 35 2C 36 36 2C 36 : 62,63,64,65,66,6
System.Net Verbose: 0 : [15028] 000000C0 : 37 2C 36 38 2C 36 39 2C-37 30 2C 37 31 2C 37 32 : 7,68,69,70,71,72
System.Net Verbose: 0 : [15028] 000000D0 : 2C 37 33 2C 37 34 2C 37-35 2C 37 36 2C 37 37 2C : ,73,74,75,76,77,
System.Net Verbose: 0 : [15028] 000000E0 : 37 38 2C 37 39 2C 38 30-2C 38 31 2C 38 32 2C 38 : 78,79,80,81,82,8
System.Net Verbose: 0 : [15028] 000000F0 : 33 2C 38 34 2C 38 35 2C-38 36 2C 38 37 2C 38 38 : 3,84,85,86,87,88
System.Net Verbose: 0 : [15028] 00000100 : 2C 38 39 2C 39 30 2C 39-31 2C 39 32 2C 39 33 2C : ,89,90,91,92,93,
System.Net Verbose: 0 : [15028] 00000110 : 39 34 2C 39 35 2C 39 36-2C 39 37 2C 39 38 2C 39 : 94,95,96,97,98,9
System.Net Verbose: 0 : [15028] 00000120 : 39 2C 31 30 30 2C 31 30-31 2C 31 30 32 2C 31 30 : 9,100,101,102,10
System.Net Verbose: 0 : [15028] 00000130 : 33 2C 31 30 34 2C 31 30-35 2C 31 30 36 2C 31 30 : 3,104,105,106,10
System.Net Verbose: 0 : [15028] 00000140 : 37 2C 31 30 38 2C 31 30-39 2C 31 31 30 2C 31 31 : 7,108,109,110,11
System.Net Verbose: 0 : [15028] 00000150 : 31 2C 31 31 32 2C 31 31-33 2C 31 31 34 2C 31 31 : 1,112,113,114,11
System.Net Verbose: 0 : [15028] 00000160 : 35 2C 31 31 36 2C 31 31-37 2C 31 31 38 2C 31 31 : 5,116,117,118,11
System.Net Verbose: 0 : [15028] 00000170 : 39 2C 31 32 30 2C 31 32-31 2C 31 32 32 2C 31 32 : 9,120,121,122,12
System.Net Verbose: 0 : [15028] 00000180 : 33 2C 31 32 34 2C 31 32-35 2C 31 32 36 2C 31 32 : 3,124,125,126,12
System.Net Verbose: 0 : [15028] 00000190 : 37 2C 31 32 38 2C 31 32-39 2C 31 33 30 2C 31 33 : 7,128,129,130,13
System.Net Verbose: 0 : [15028] 000001A0 : 31 2C 31 33 32 2C 31 33-33 2C 31 33 34 2C 31 33 : 1,132,133,134,13
System.Net Verbose: 0 : [15028] 000001B0 : 35 2C 31 33 36 2C 31 33-37 2C 31 33 38 2C 31 33 : 5,136,137,138,13
System.Net Verbose: 0 : [15028] 000001C0 : 39 2C 31 34 30 2C 31 34-31 2C 31 34 32 2C 31 34 : 9,140,141,142,14
System.Net Verbose: 0 : [15028] 000001D0 : 33 2C 31 34 34 2C 31 34-35 2C 31 34 36 2C 31 34 : 3,144,145,146,14
System.Net Verbose: 0 : [15028] 000001E0 : 37 2C 31 34 38 2C 31 34-39 2C 31 35 30 2C 31 35 : 7,148,149,150,15
System.Net Verbose: 0 : [15028] 000001F0 : 31 2C 31 35 32 2C 31 35-33 2C 31 35 34 2C 31 35 : 1,152,153,154,15
System.Net Verbose: 0 : [15028] 00000200 : 35 2C 31 35 36 2C 31 35-37 2C 31 35 38 2C 31 35 : 5,156,157,158,15
System.Net Verbose: 0 : [15028] 00000210 : 39 2C 31 36 30 2C 31 36-31 2C 31 36 32 2C 31 36 : 9,160,161,162,16
System.Net Verbose: 0 : [15028] 00000220 : 33 2C 31 36 34 2C 31 36-35 2C 31 36 36 2C 31 36 : 3,164,165,166,16
System.Net Verbose: 0 : [15028] 00000230 : 37 2C 31 36 38 2C 31 36-39 2C 31 37 30 2C 31 37 : 7,168,169,170,17
System.Net Verbose: 0 : [15028] 00000240 : 31 2C 31 37 32 2C 31 37-33 2C 31 37 34 2C 31 37 : 1,172,173,174,17
System.Net Verbose: 0 : [15028] 00000250 : 35 2C 31 37 36 2C 31 37-37 2C 31 37 38 2C 31 37 : 5,176,177,178,17
System.Net Verbose: 0 : [15028] 00000260 : 39 2C 31 38 30 2C 31 38-31 2C 31 38 32 2C 31 38 : 9,180,181,182,18
System.Net Verbose: 0 : [15028] 00000270 : 33 2C 31 38 34 2C 31 38-35 2C 31 38 36 2C 31 38 : 3,184,185,186,18
System.Net Verbose: 0 : [15028] 00000280 : 37 2C 31 38 38 2C 31 38-39 2C 31 39 30 2C 31 39 : 7,188,189,190,19
System.Net Verbose: 0 : [15028] 00000290 : 31 2C 31 39 32 2C 31 39-33 2C 31 39 34 2C 31 39 : 1,192,193,194,19
System.Net Verbose: 0 : [15028] 000002A0 : 35 2C 31 39 36 2C 31 39-37 2C 31 39 38 2C 31 39 : 5,196,197,198,19
System.Net Verbose: 0 : [15028] 000002B0 : 39 2C 32 30 30 2C 32 30-31 2C 32 30 32 2C 32 30 : 9,200,201,202,20
System.Net Verbose: 0 : [15028] 000002C0 : 33 2C 32 30 34 2C 32 30-35 2C 32 30 36 2C 32 30 : 3,204,205,206,20
System.Net Verbose: 0 : [15028] 000002D0 : 37 2C 32 30 38 2C 32 30-39 2C 32 31 30 2C 32 31 : 7,208,209,210,21
System.Net Verbose: 0 : [15028] 000002E0 : 31 2C 32 31 32 2C 32 31-33 2C 32 31 34 2C 32 31 : 1,212,213,214,21
System.Net Verbose: 0 : [15028] 000002F0 : 35 2C 32 31 36 2C 32 31-37 2C 32 31 38 2C 32 31 : 5,216,217,218,21
System.Net Verbose: 0 : [15028] 00000300 : 39 2C 32 32 30 2C 32 32-31 2C 32 32 32 2C 32 32 : 9,220,221,222,22
System.Net Verbose: 0 : [15028] 00000310 : 33 2C 32 32 34 2C 32 32-35 2C 32 32 36 2C 32 32 : 3,224,225,226,22
System.Net Verbose: 0 : [15028] 00000320 : 37 2C 32 32 38 2C 32 32-39 2C 32 33 30 2C 32 33 : 7,228,229,230,23
System.Net Verbose: 0 : [15028] 00000330 : 31 2C 32 33 32 2C 32 33-33 2C 32 33 34 2C 32 33 : 1,232,233,234,23
System.Net Verbose: 0 : [15028] 00000340 : 35 2C 32 33 36 2C 32 33-37 2C 32 33 38 2C 32 33 : 5,236,237,238,23
System.Net Verbose: 0 : [15028] 00000350 : 39 2C 32 34 30 2C 32 34-31 2C 32 34 32 2C 32 34 : 9,240,241,242,24
System.Net Verbose: 0 : [15028] 00000360 : 33 2C 32 34 34 2C 32 34-35 2C 32 34 36 2C 32 34 : 3,244,245,246,24
System.Net Verbose: 0 : [15028] 00000370 : 37 2C 32 34 38 2C 32 34-39 2C 32 35 30 2C 32 35 : 7,248,249,250,25
System.Net Verbose: 0 : [15028] 00000380 : 31 2C 32 35 32 2C 32 35-33 2C 32 35 34 2C 32 35 : 1,252,253,254,25
System.Net Verbose: 0 : [15028] 00000390 : 35 2C 32 35 36 2C 32 35-37 2C 32 35 38 2C 32 35 : 5,256,257,258,25
System.Net Verbose: 0 : [15028] 000003A0 : 39 2C 32 36 30 2C 32 36-31 2C 32 36 32 2C 32 36 : 9,260,261,262,26
System.Net Verbose: 0 : [15028] 000003B0 : 33 2C 32 36 34 2C 32 36-35 2C 32 36 36 2C 32 36 : 3,264,265,266,26
System.Net Verbose: 0 : [15028] 000003C0 : 37 2C 32 36 38 2C 32 36-39 2C 32 37 30 2C 32 37 : 7,268,269,270,27
System.Net Verbose: 0 : [15028] 000003D0 : 31 2C 32 37 32 2C 32 37-33 2C 32 37 34 2C 32 37 : 1,272,273,274,27
System.Net Verbose: 0 : [15028] 000003E0 : 35 2C 32 37 36 2C 32 37-                        : 5,276,27
System.Net Verbose: 0 : [15028] Exiting ConnectStream#56140151::Read()  -> Int32#1000
Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • The logging shows only the actual .NET framework reads on the input buffer, but it doesn't tell us anything about the actual data coming in over the wire it appears. It appears (can't confirm) that something is preloading a chunk of data even before we start reading from the response bufffer - by the time I call ReadStream() there's already content traffic on the wire. – Rick Strahl Jan 11 '14 at 02:49
  • @RickStrahl One other thing to consider. You could do SendAsync() with ResponseHeadersRead and then immediately Cancel the request. That should abort the HttpWebRequest. It might minimize the number of bytes going across the wire. – Darrel Miller Jan 11 '14 at 17:29