Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Загрузчик на idHTTP зависает при загрузке страниц


Страницы:   1 2

Pcrepair ©   (2013-01-07 03:14:00) 

Добрый день. Есть код загрузчика страниц(вызывается в поток):

function TLoader.LoadHtmlCode(const PageUrl: String):string;
var
ErrorData:string; (*ответ сервера в тестовом виде*)
ResponseCode:integer; (*ответ сервера в виде кода ошибки*)
begin
  try
    (*---------настройка параметров закачки-----------*)
    FIdHttp.Request.UserAgent:=GetRandomUserAgent; (*получаем случайное значение Юзер-Агент*)
    FIdHttp.Request.AcceptLanguage:='ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3'; (*вроде нужно*)
    FIdHttp.Request.AcceptCharSet:='windows-1251,utf-8;q=0.7,*;q=0.3'; (*вроде нужно*)
    FIdHttp.ConnectTimeout:=10000;
    FIdHttp.ReadTimeout:=10000;
    FIdHttp.IOHandler:=FSSL;
    FIdHttp.HandleRedirects:=True;
    Result:=AnsiLowerCase(FIdHttp.Get(PageUrl));
      except
        Result:=PageUrl;
        (*тут вызов ПРОЦ для записи ответа сервера и УРЛ в лог*)
      end;
     Exit;  (*выход из функции. в РЕЗУЛЬТАТ содержится последнее значение*)
  end;
end;

1. При высокой скорости трафика все работает нормально:
- загрузка 100 УРЛ за 20...25 сек (10 потоков одновременно)
- никаких утечек памяти
практически все как предначертано работает
2. При наличие потребителя трафика(другой РС в сети с работающим ТОРРЕНТ, источник интернета - роутер 3 мбит\сек):
- загрузка 97...100 УРЛ за 60...120 сек
- один или два потока зависают(есть на форме индикатор числа работающих потоков)при закачке УРЛ и могут висеть часами, пока не закрыть программу
- никакой зависимости от УРЛ нет, в одном тесте одни УРЛ не закачиваются в другом другие
- еще одна особенность: в логе фиксируется ответ сервера. при наличие конкурента на трафик от 10 до 30 УРЛ не загружаются(то же различные, от теста к тесту), хотя ответ сервера = 200 (ну это не самая большая проблема, скоро будет добавлен код перезакачки УРЛ), но о чем то этот факт говорит?

Внимание! Вопросы:
1. в чем причина такого поведения TidHttp?
возможно надо что то настроить в параметрах загрузчика?
2. возможно ли ввести в поток загрузчика таймер типа:

procedure TLoader.Execute;
begin
 CallTimer;
 FIdHttp.Get(PageUrl);
end;

procedure TLoader.CallTimer;
begin
 (*тут реализация таймера на 100 сек, но на чем? TTimer явно не подойдет*)
  Событие OnTimer вызывает
  FIdHttp.Socket.Close; (*если через 100 сек страница не закачается и поток не сдохнет
  принудительно закрыть idHTTP, поток после тоже закроется*)
  может кто подскажет реализацию таймера, на чем бы его сделать?
end;


почитал на форумах что нашел, похоже таймер единственный вариант решить эту проблему


brother   (2013-01-08 08:28:00) [1]

[34] Формулировка сообщения тайм аута точна?


Anatoly Podgoretsky   (2013-01-08 00:20:00) [2]

> Pcrepair  (07.01.2013 22:31:34)  [34]

Тростниковый таймаут?
Что это такое?


DVM   (2013-01-07 22:36:00) [3]


> я тут не просто так узнаю как можно прихлопнуть idhttp

Я ж тебе уже 3 раза написал как его прихопнуть. Закрыть евойный сокет из другого потока. Но для этого как минимум надо иметь список потоков работающих.


Сергей М.   (2013-01-07 22:35:00) [4]


> точнее были сообщения Reed Timed Out но они к ситуации отношения
> не имеют


Как это не имеют ? Самое прямое отношение они имеют !
Как раз при этом исключении ты и решаешь свою проблему безо всяких "прихлопываний".


Сергей М.   (2013-01-07 22:33:00) [5]


> как можно получит данные о том что происходит в зависшем
> соединении


Средствами той самой стандартной утилиты netstat.
Еще удобней средствами сетевых утилит от Руссиновича.


> я тут не просто так узнаю как можно прихлопнуть idhttp


Тебе же сказали как - закрыв сокет из другого потока.


Pcrepair   (2013-01-07 22:31:00) [6]

пробовал и само искл от ИНДИ

on E:EIdHTTPProtocolException do
    begin
    ShowMessage(E.ErrorMessage);

но там тоже ничего НЕБЫЛО
точнее были сообщения Reed Timed Out но они к ситуации отношения не имеют, это просто незагруженные страницы


Pcrepair   (2013-01-07 22:24:00) [7]


> А доступ к индикатору синхронизован? Кто и как обновляет
> его? Откуда уверенность что там верное значение?

синхронизация по КС
там просто обращение к ГП типа ЧИСЛО и отображение значения в ЛЕЙБЛ


> Я спрашиваю в каком состоянии находится соединение, создаваемое
> неким "зависшим" IdHTTP ?
> NetStat что говорит по этому поводу ?

когда узнаю что такое NetStat тогда расскажу
а как можно получит данные о том что происходит в зависшем соединении, когда рассоеденить его можно только отключив программу. при этом выскакивает сообщение об утечке памяти
я тут не просто так узнаю как можно прихлопнуть idhttp


sniknik   (2013-01-07 22:19:00) [8]

> Нужен внешний менеджер который будет потоки мониторить.
а кто проверяет проверяющего?

в смысле, проблема в его способе программирования (синхронизация, игнорирование эксептов, ets. х.з. что), он вместо определения что это "навернет" тем же способом еще уровень из потоков... что делать когда подобное возникнет уже на этом уровне?

> ErrorData:=FIdHttp.Response.ResponseText;
вопрос. что это? вот если нет ответа, даже ошибочного от сервера, эксепт же произошёл, кто знает откуда, на каком этапе, например не доходя еще до собственно запроса, и тут идет попытка считать этот ответ... что будет? там же не просто переменная, там возможно свойство, с собственным обработчиком...
(не хочу смотреть сам, да и негде сейчас, новый комп, т.что чисто теоретически, на мысль навести...)

p.s. есть же нормальное сообщение в эксепте. почему не использовать его (+ там есть случаи реальных ошибок сервера 400/404/... они отдельно в инди вроде. ну это после добавить). зачем сразу извращения?


Сергей М.   (2013-01-07 22:14:00) [9]


> ну вообще есть вот такой эффект


Причем здесь "эффект" ?

Я спрашиваю в каком состоянии находится соединение, создаваемое неким "зависшим" IdHTTP ?
NetStat что говорит по этому поводу ?


DVM   (2013-01-07 22:14:00) [10]


> Pcrepair ©   (07.01.13 22:06) [29]

Очень много скользких мест.

Вот хотя бы фраза:

есть на форме индикатор числа работающих потоков

А доступ к индикатору синхронизован? Кто и как обновляет его? Откуда уверенность что там верное значение?

Загрузка сети просто ускорят проявление проблем, но они имхо не связаны с загрузкой.


Pcrepair   (2013-01-07 22:06:00) [11]


> че такое CS ? Это поле класса TLoader? Если да, подравляю
> тебя у тебя доступ к логу не синхронизован.

это конечно ГлобПерем

> И при этом ты убедился что соединение действительно установлено,
>  но трафик по нему нулевой (или ненулевой, но не прогрессирует)
> ?

ну вообще есть вот такой эффект(повтор заголовка темы):
При наличие потребителя трафика(другой РС в сети с работающим ТОРРЕНТ, источник интернета - роутер 3 мбит\сек):
- загрузка 97...100 УРЛ за 60...120 сек
- один или два потока зависают(есть на форме индикатор числа работающих потоков)при закачке УРЛ и могут висеть часами, пока не закрыть программу
- никакой зависимости от УРЛ нет, в одном тесте одни УРЛ не закачиваются в другом другие
- еще одна особенность: в логе фиксируется ответ сервера. при наличие конкурента на трафик от 10 до 30 УРЛ не загружаются(то же различные, от теста к тесту), хотя ответ сервера = 200
это отсюда ErrorData:=FIdHttp.Response.ResponseText;(*тут ответ сервера*)


DVM   (2013-01-07 22:00:00) [12]


> Pcrepair ©   (07.01.13 21:49) [24]


> вообще в этой теме хотелось рассмотреть возможность самоликвидации
> потока по времени

Если поток блокирован какой то операцией то он не может самоликвидироваться, он же не мюнхаузен, чтобы сам себя вытащить из болота. А вот выйти ему из состояния блокировки (если блокировку действительно вызывает Indy) можно закрыв сокет извне, чего непонятного то?
Нужен внешний менеджер который будет потоки мониторить.


Сергей М.   (2013-01-07 21:53:00) [13]


> само собой


И при этом ты убедился что соединение действительно установлено, но трафик по нему нулевой (или ненулевой, но не прогрессирует) ?


DVM   (2013-01-07 21:53:00) [14]


> Pcrepair ©   (07.01.13 21:49) [24]

 (*----27.12.2012 синхронизация через КС--------*)
         CS.Enter;  (*вход в КС*)
           ErrorLog(PageUrl+#10+ErrorData); (*только для контроля*)
         Cs.Leave;  (*выход из КС*)
       (*---------------------------------------------*)

че такое CS ? Это поле класса TLoader? Если да, подравляю тебя у тебя доступ к логу не синхронизован.


Pcrepair   (2013-01-07 21:51:00) [15]


> и для ConnectTimeout тоже ?

само собой


Pcrepair   (2013-01-07 21:49:00) [16]


> Ты лучше дай URL на котором гарантированно такое происходит,
>  я возьму TidHTTP и выполню Get для данного URL и получу
> зависание. И все станет ясно.

сверху написано - в каждом цикле загрузки сбойные УРЛ разные
к тому же этот косяк проявляется только при многопоточной загрузке и ТОЛЬКО когда трафик занят закачкой тореннта и не просто торрента а с ЛОСТФИЛЬМ

вся синхронизация идет через КС - куда больше? да там и всех делов: вывод страницы в накопитель(СПИСОК)

исключение тут:

Result:=AnsiLowerCase(FIdHttp.Get(PageUrl));
    except (*да иск макс уровня*)
        Result:=PageUrl+(' = Total Error');
        ErrorData:=FIdHttp.Response.ResponseText;
       (*----27.12.2012 синхронизация через КС--------*)
         CS.Enter;  (*вход в КС*)
           ErrorLog(PageUrl+#10+ErrorData); (*только для контроля*)
         Cs.Leave;  (*выход из КС*)
       (*---------------------------------------------*)
       Exit;
  end;
end;

вообще в этой теме хотелось рассмотреть возможность самоликвидации потока по времени
менеджер рассмотрим в другой теме. если будут вопросы


DVM   (2013-01-07 21:48:00) [17]


>  еще рискну предположить, что у нас опять может иметь место
> проблема синхронизации между потоками.

вот, например,


     except
       Result:=PageUrl;
       (*тут вызов ПРОЦ для записи ответа сервера и УРЛ в лог*)
     end;


Эта самая ПРОЦ она синхронизирует доступ к логу?


DVM   (2013-01-07 21:45:00) [18]


> Pcrepair ©   (07.01.13 21:30) [18]


> получается это все мелкие косячки инди

Не стоит торопиться с выводами, косячки есть конечно, они исправляются, например со времен той ветки многое исправилось.


Сергей М.   (2013-01-07 21:43:00) [19]


> установил в 100 сек. но не грохается


и для ConnectTimeout тоже ?


DVM   (2013-01-07 21:38:00) [20]


> Pcrepair ©   (07.01.13 19:36) [10]


> так ведь нету ошибки

Согласен со sniknik, скорее всего ты задавил где то исключение благополучно вот и нет его. Ты лучше дай URL на котором гарантированно такое происходит, я возьму TidHTTP и выполню Get для данного URL и получу зависание. И все станет ясно.

Учитывая предыдущие твои вопросы еще рискну предположить, что у нас опять может иметь место проблема синхронизации между потоками.

Прервать любую операцию с сокетами можно без проблем закрыв сокет из другого потока. Если возвратиться к теме пула потоков, то вот этот самый менеджер потоков в отдельном потоке мог бы проверять, сколько времени работает тот или иной поток и если работа затянулась - закрывать соответствующий сокет, че бы там ни было, вылетит исключение и закачка прервется.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо