HttpWebResponse.GetResponseStream (): когда передается тело ответа?

Я использую класс System.Net.HttpWebRequest для реализации простого Загрузчик HTTP, который можно приостановить, отменить и даже возобновить после его отмены (с заголовком запроса HTTP Range).

Понятно, что HttpWebRequest.GetResponse () - это когда HTTP-запрос фактически отправляется на сервер, а метод возвращается, когда получен HTTP-ответ (или наступает тайм-аут). Однако тело ответа представлено Stream, что заставляет меня задаться вопросом, действительно ли тело ответа передается с заголовком ответа (т.е. оно уже загружено, когда GetResponse () возвращается), или оно загружается только по запросу, когда я пытаюсь читать из потока ответов? Или, может быть, когда я вызываю метод HttpWebResponse.GetResponseStream ()?

К сожалению, документация msdn не говорит об этом, и я недостаточно знаю о протоколе HTTP, чтобы сказать.

Как в этом случае ведут себя фрагментированные передачи и т.п. (то есть как мне обрабатывать их в моем приложении C #)? Когда на самом деле данные ответа загружаются с сервера?


person ShdNx    schedule 10.07.2011    source источник
comment
FWIW, это действительно больше о TCP / IP, чем о HTTP. HTTP всегда пытается отправить полный ответ. Вопрос, который вы задаете: читает ли .NET тело объекта HTTP из сокета независимо от того, читаю ли я поток ответа или нет, и я почти уверен, что ответ - да.   -  person EricLaw    schedule 10.07.2011


Ответы (1)


Все зависит от TCP, основного протокола HTTP. Принцип работы TCP заключается в том, что данные отправляются сегментами. Каждый раз, когда клиент отправляет сегмент на сервер, среди отправленных данных есть информация о том, сколько дополнительных данных он готов принять. Обычно это соответствует некоторому буферу со стороны клиента. Когда клиент получает некоторые данные, он также отправляет сегмент на сервер, подтверждая полученные данные.

Итак, если предположить, что клиент очень медленно обрабатывает полученные данные, последовательность событий может выглядеть так:

  1. Соединение установлено, клиент говорит, сколько данных готов к приему.
  2. Сервер отправляет клиенту один или несколько сегментов, общее количество данных в них не превышает суммы, которую клиент сказал, что он готов к приему.
  3. Клиент говорит серверу: я получил данные, которые вы мне отправили, но пока больше не присылайте.
  4. Клиент обрабатывает часть данных.
  5. Клиент говорит серверу: вы можете отправить мне еще x байтов данных

Что это значит в отношении GetResponse()? Когда вы вызываете GetResponse(), клиент отправляет запрос, читает HTTP-заголовок ответа (который обычно помещается в один сегмент, но может быть больше) и возвращается. На этом этапе, если вы не начинаете читать поток ответа (который вы получаете, вызывая GetResponseStream()), некоторые данные с сервера принимаются, но только для заполнения буфера. Когда он заполнен, данные больше не передаются, пока вы не начнете читать поток ответа.

person svick    schedule 10.07.2011
comment
Итак, если я правильно понимаю, тело ответа отправляется только тогда, когда я читаю из потока ответа. Это немного сложнее, чем я думал, но я понял. Спасибо! Еще один вопрос, прежде чем я приму ваш ответ: я знаю, что сервер может возвращать данные отдельными частями (частичная передача). В этом случае это просто означает, что чтение из потока ответа будет заблокировано до тех пор, пока не станет доступен следующий фрагмент, верно? - person ShdNx; 10.07.2011
comment
@ShdNx, это не совсем так. Часть ответа отправляется, даже если вы не читаете поток ответа, но, скорее всего, не весь ответ. Кодирование с фрагментированной передачей практически ничего не меняет. Это нормально, что чтение из потока ответа блокируется даже без использования передачи по частям. А при передаче по частям поток не должен блокироваться до тех пор, пока не станет доступен весь следующий фрагмент, только до тех пор, пока не станет доступна его часть. - person svick; 10.07.2011