Открыть список
Как стать автором
Обновить

Комментарии 12

А можно на пальцах рассказать, зачем для чисто серверных операций использовать именно HttpClient, а не HttpWebRequest? Мне всегда казалось, что HttpClient нужен чтоб странички грузить «как в браузере».
С точки зрения HTTP протокола, между API, которое возвращает JSON, и обычными страницами, отдающими клиенту HTML, принципиальной разницы нет — это просто разные типы контента. Соответственно, нет и разделения на то, какие типы контента какими классами лучше всего получать. Что выбрать, HttpWebRequest или HttpClient, скорее зависит от удобства, гибкости и производительности который дает каждый их них.

HttpWebRequest очень низкоуровневый, каждый запрос нужно конструировать заново, и на это уходит заметно больше кода, чем на те же действия через HttpClient. При этом, если надо в юнит-тестах сделать мок вместо реальных обращений по сети, то с HttpWebRequest это будет проблематичным: по-хорошему придется вокруг этого класса делать фабрику и в коде использовать ее методы вместо явного создания HttpWebRequest. По сути HttpClient — и есть своего рода фабрика запросов. Она конечно же добавляет своего оверхеда в плане производительности, но для 99% случаев я думаю этим можно пренебречь. В то же время HttpClient значительно упрощает реализацию многих сценариев работы с HTTP и по сути является фасадом к более низкоуровневым классам, таким как HttpWebRequest. Но как и в любой абстракции, в нем есть неявные моменты, которые и описаны в статье.
Для загрузки страничек «как в браузере» есть headless браузеры.

А HttpClient — это тот же HttpWebRequest, но с более удобным API.
>Если нужна как можно более быстрая реакция на изменение IP адреса, например, как в случае балансировки через DNS round-robin
Разве ДНС не возвращает сразу несколько ИП-ов, в которые резолвится домен (getaddrinfo)? Сам HttpClient не сможет переключаться между ними, без доп. запросов к ДНС?
С DNS можно сразу получить несколько IP, но в общем случае round-robin работает на базе поведения DNS сервера — либо с каждым запросом возвращается другой IP адрес (по кругу), либо возвращается полный список, но каждый раз с разным порядком адресов (https://en.wikipedia.org/wiki/Round-robin_DNS, blogs.technet.microsoft.com/networking/2009/04/17/dns-round-robin-and-destination-ip-address-selection). Я на практике не наблюдал, чтобы HttpClient при работе с доменом, зарегистрированным на несколько IP адресов, сам бы перебирал их с каждым новым подключением.
спасибо, очень интересная и познавательная статья.
побольше бы таких.
буквально на днях делали обмен с использованием HttpClient, нас сильно озадачила скорость передачи данных на локальной тачке и по сети, а все дело оказалось как раз в количестве одновременных подключений, ну и на грабли с утечкой подключений то же наступили ))))
Вот ещё интересное наблюдение ко всему, что наследуется от WebRequest.
Задача:
передать на сайт данные с помощью POST запроса с компьютера, с доступом в сеть через прокси;

Выставляем параметры прокси и аутентификации из настроек сети (System.Net.WebProxy.GetDefaultProxy(), System.Net.CredentialCache.DefaultNetworkCredentials)

Отправляем POST-запрос, если объем переданных данных меньше 100 кБ, все ОК (сначала возвращается 407, потом 200)
Если объем больше — только 407, данные не передаются, на клиент возвращается только таймаут операции. Грешили на прокси, но там таких ограничений не стояло. Подозреваю, что это все же ошибка многопоточности в C#, но могу провести расследование, если кому интересно.
Позвольте такой вопрос, косвенно связанный с темой:
Есть, к примеру, 100 устройств, распределенных по сети, которые, допустим, два раза в секунду шлют данные на сервер. Данные — строка из ~20 символов. Сервер, в свою очередь, тоже шлет данные на все устройства раз в 3 сек- хертбит. Какую схему сетевого взаимодействия в этом случае корректнее будет применить — постоянно держать открытым tcp-канал, открывать tcp-канал для отправки сообщения и закрывать его за собой или перейти к http-запросам? Испытания/замеры скорости не показали радикальной разницы. Искал ответы на разных тематических форумах, но аргументированного ответа не нашел, решил, что раз наткнулся на эту тему, то это знак.
На таком масштабе радикальной разницы не будет. Я так понимаю, подключение не использует SSL, т.е. дополнительные затраты на SSL handshake при установке соединения не идут. Сервер легко выдержит 100 одновременных постоянных подключений, а сдругой стороны — передача данных не настолько частая, чтобы установка соединения вносила какую-то заметную задержку (при условии что канал не настолько плохой, что и 20 байт не всегда быстро доходят, если доходят вообще :)).

В целом, если нет перспективы роста на десятки-сотни тысяч соединений (и даже при такой перспективе тоже могут быть варианты с постоянными соединениями), я бы держал постоянно открытое TCP соединение и по нему бы общался, пересоздавая в случае сбоев.
Шикарная статья, большое спасибо
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.