Почему этот код WebRequest работает медленно?
Я запросил 100 страниц, что все 404. Я написал
{
var s = DateTime.Now;
for(int i=0; i < 100;i++)
DL.CheckExist("http://google.com/lol" + i.ToString() + ".jpg");
var e = DateTime.Now;
var d = e-s;
d=d;
Console.WriteLine(d);
}
static public bool CheckExist(string url)
{
HttpWebRequest wreq = null;
HttpWebResponse wresp = null;
bool ret = false;
try
{
wreq = (HttpWebRequest)WebRequest.Create(url);
wreq.KeepAlive = true;
wreq.Method = "HEAD";
wresp = (HttpWebResponse)wreq.GetResponse();
ret = true;
}
catch (System.Net.WebException)
{
}
finally
{
if (wresp != null)
wresp.Close();
}
return ret;
}
Два запуска показывают, что это занимает 00:00:30.7968750 и 00:00:26.8750000. Тогда я попробовал Firefox и использовать следующий код
<html>
<body>
<script type="text/javascript">
for(var i=0; i<100; i++)
document.write("<img src=http://google.com/lol" + i + ".jpg><br>");
</script>
</body>
</html>
Используя мое время компа и считая это было примерно 4 секунды. 4 секунды на 6,5-7,5 быстрее, чем мое приложение. Я планирую сканировать тысячи файлов, поэтому большая трудность займет 3,75 часа вместо 30 минут. Как я могу сделать этот код быстрее? Я знаю, что кто-то скажет, что Firefox кэширует изображения, но я хочу сказать: 1) ему все еще нужно проверить заголовки с удаленного сервера, чтобы увидеть, обновлено ли оно (что я и хочу сделать в моем приложении) 2) Я не Получив тело, мой код должен запрашивать только заголовок. Итак, как мне решить это?
7 ответов
Возможно, Firefox выдает несколько запросов одновременно, тогда как ваш код выполняет их один за другим. Возможно, добавление потоков ускорит вашу программу.
Я заметил, что HttpWebRequest
виснет по первому запросу. Я провел некоторое исследование, и, похоже, происходит то, что запрос настраивает или автоматически определяет прокси. Если вы установите
request.Proxy = null;
в объекте веб-запроса вы можете избежать начальной задержки.
С автоопределением прокси:
using (var response = (HttpWebResponse)request.GetResponse()) //6,956 ms
{
}
Без автоматического определения прокси:
request.Proxy = null;
using (var response = (HttpWebResponse)request.GetResponse()) //154 ms
{
}
Измените свой код на асинхронный getresponse
public override WebResponse GetResponse() {
•••
IAsyncResult asyncResult = BeginGetResponse(null, null);
•••
return EndGetResponse(asyncResult);
}
Ответ меняется HttpWebRequest/HttpWebResponse только на WebRequest/WebResponse. Это решило проблему.
Установить cookie - дело, и вы должны добавить
AspxAutoDetectCookieSupport=1
как этот код
req.CookieContainer = new CookieContainer();
req.CookieContainer.Add(new Cookie("AspxAutoDetectCookieSupport", "1") { Domain = target.Host });
Вы пытались открыть тот же URL в IE на компьютере, на котором развернут ваш код? Если это компьютер с Windows Server, то иногда это происходит из-за того, что запрашиваемый вами URL отсутствует в списке безопасных сайтов IE (который работает с HttpWebRequest). Вам просто нужно добавить это.
У вас есть больше информации, которую вы могли бы опубликовать? Я делал что-то подобное и сталкивался с кучей проблем с HttpWebRequest раньше. Все уникально. Так что больше информации поможет.
Кстати, вызов этого с использованием асинхронных методов не очень поможет в этом случае. Это не сокращает время загрузки. Это просто не блокирует ваш вызывающий поток, вот и все.
ОК, если вы получаете код состояния 404 для всех веб-страниц, то это связано с не указанием учетных данных. Так что вам нужно добавить
wreq.Credentials = CredentialCache.DefaultCredentials;
Тогда вам также может встретиться код состояния = 500, для которого вам нужно указать User Agent. Который выглядит примерно так, как показано ниже
wreq.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0";
"Экземпляр WebClient не отправляет необязательные заголовки HTTP по умолчанию. Если для вашего запроса требуется необязательный заголовок, необходимо добавить заголовок в коллекцию заголовков. Например, чтобы сохранить запросы в ответе, необходимо добавить заголовок агента пользователя. Кроме того, серверы могут возвращать 500 (Внутренняя ошибка сервера), если отсутствует заголовок пользовательского агента."
ссылка: https://msdn.microsoft.com/en-us/library/system.net.webclient(v=vs.110).aspx
Для повышения производительности HttpWebrequest необходимо добавить
wreq.Proxy=null
теперь код будет выглядеть так:
static public bool CheckExist(string url)
{
HttpWebRequest wreq = null;
HttpWebResponse wresp = null;
bool ret = false;
try
{
wreq = (HttpWebRequest)WebRequest.Create(url);
wreq.Credentials = CredentialCache.DefaultCredentials;
wreq.Proxy=null;
wreq.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0";
wreq.KeepAlive = true;
wreq.Method = "HEAD";
wresp = (HttpWebResponse)wreq.GetResponse();
ret = true;
}
catch (System.Net.WebException)
{
}
finally
{
if (wresp != null)
wresp.Close();
}
return ret;
}
Когда вы закончите, закройте поток ответов, поэтому в свой checkExist() добавьте wresp.Close() после wresp = (HttpWebResponse)wreq.GetResponse();