Я пытаюсь использовать новый класс HttpClient (в .NET 4.5) для получения частичных ответов с сервера, чтобы проверить содержимое. Мне нужно ограничить размер данных, полученных в первые несколько байтов содержимого HTTP-запросов, чтобы ограничить использование полосы пропускания.
Я не смог этого сделать. Я попытался использовать GetAsync (url, HttpCompletionOption.ResponseHeadersRead), а затем использовать Content.ReadAsStream(), пытаясь только прочитать заголовки, а затем прочитать поток ответов в небольшом фрагменте. Я также попробовал GetStreamAsync(), а затем прочитал поток Content с небольшим фрагментом (1000 байт).
В обоих случаях оказывается, что HttpClient вытягивает и буферизует весь HTTP-ответ, а не просто считывает запрошенный байт из потока.
Изначально я использовал Fiddler для мониторинга данных, но понял, что Fiddler действительно может вызвать проксирование всего содержимого. Я переключился на использование трассировки System.Net(который показывает):
ConnectStream#6044116::ConnectStream(Buffered 16712 bytes.)
который является полным размером, а не только прочитанным 1000 байтами. Я также дважды проверял в Wireshark, чтобы убедиться, что действительно полный контент натягивается на провод, и это так. С более крупным контентом (например, с каналом 110k) я получаю около 20 тыс. Данных до того, как поток TCP/IP будет усечен.
Двумя способами я попытался прочитать данные:
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);
и
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);
Оба из них производят почти идентичную трассировку .NET, которая включает в себя буферизованное чтение.
Возможно ли, что HttpClient действительно прочитал только небольшой фрагмент Http Repsonse, а не весь ответ, чтобы не использовать полную пропускную способность? IOW есть способ отключить любую буферизацию в HTTP-соединении с помощью HttpClient или HttpWebRequest?
Update: После более обширного тестирования он выглядит как буфер HttpClient и HttpWebRequest, первые несколько кадров TCP/IP - предположительно для обеспечения захвата заголовка HTTP. Поэтому, если вы возвращаете достаточно маленький запрос, он, как правило, загружается полностью, потому что он в этом inital bufferred читается. Но при загрузке большего URL-адреса контента содержимое становится усеченным. Для HttpClient это около 20k, для HttpWebRequest где-то около 8k для меня.
Использование TcpClient не имеет проблем с буферизацией. При его использовании я получаю чтение содержимого с размером прочитанного плюс немного больше для ближайшего перекрытия размера буфера, но это включает заголовок HTTP. Использование TcpClient на самом деле не является для меня вариантом, так как нам приходится иметь дело с областями SSL, Redirects, Auth, Chunked и т.д. В этот момент я бы посмотрел на реализацию полного пользовательского HTTP-клиента только для того, чтобы включить буферизацию.