Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.03.2016, 20:14   #1
niva622
Форумчанин
 
Регистрация: 31.12.2006
Сообщений: 114
По умолчанию Многопоточная проверка сайтов

Всем доброго времени суток, хотел бы подсказку от знатоков, хочу сделать многопоточную проверку сайтов методом http, запускаю, в итоге то-ли потоки путаются то ли еще что то.
Код:
procedure TNewThread.Execute;
var
 HTTP: TIdHTTP;
 i:Integer;

begin
     while Acc<>ts.Count-1 do
         begin
   CS.Enter;
   Inc(Acc);
   CS.Leave;
         HTTP:=TIdHTTP.create(nil);
    HTTP.HandleRedirects:=false;
       HTTP.ConnectTimeout:=200;
        HTTP.ReadTimeout:=200;
         try
//HTTP.Get('http://hideme.ru/'+inttostr(Acc));
      HTTP.Get('http://'+ts.Strings[Acc]+'/');
      if HTTP.ResponseText='HTTP/1.0 200 OK' then tsg.add('+') else tsg.add('+') ;

except
    tsg.add('-') ;
     end;
end;
      HTTP.Free;
       Synchronize(Sync);
end;
По сути, программа с каждым циклом увеличивает значение ACC от 1 до количества строк сайтов в стринглисте, увеличение идет в критической секции, но на выходе в итоге каша.. прошу помощи, спасибо
niva622 вне форума Ответить с цитированием
Старый 17.03.2016, 20:38   #2
eoln
Старожил
 
Аватар для eoln
 
Регистрация: 26.04.2008
Сообщений: 2,689
По умолчанию

Цитата:
Сообщение от niva622 Посмотреть сообщение
в итоге каша
Какая каша? Кашу маслом не испортишь, а потоки синхронизацией не испортишь

Нет гарантий, что в
Код:
HTTP.Get('http://'+ts.Strings[Acc]+'/');
Acc будет тот самый, который был сразу после
Код:
Inc(Acc);
В критической секции нужно запомнить Acc в другую локальную переменную и использовать только её.
Но ещё и сама проверка
Код:
while Acc<>ts.Count-1
тоже легко слетит если другой поток после этого сделает то же самое для предпоследней позиции и войдёт в КС

А тут точно всё норм?
Код:
then tsg.add('+') else tsg.add('+') ;
И если так и нужно, то всё равно опасно. ПисАть в одно место разным потокам невежливо. В синхронизу их хотя бы надо (ну или КС если нравится). Ну если это глобальная для всех потоков вещь ес-но
eoln вне форума Ответить с цитированием
Старый 17.03.2016, 21:09   #3
niva622
Форумчанин
 
Регистрация: 31.12.2006
Сообщений: 114
По умолчанию

Цитата:
А тут точно всё норм?
да это верно, просто последние несколько часов, пытаюсь доковырять этот код, и все безрезультатно... вот и накидал на скорую руку, пробывал еще создать переменную, в нее загонять ответы сервера и синхронизировать потоки, ничего не выходит.. Довольно не вкусная каша, путаются потоки в итоге рабочий сервер с ответом 200 идет в список не рабочих..
Вот так пробую не выходит

Ах да самое интересное, если к ответу серера добавить переменную cur или acc то начинается она с 4, т.к запускаю в 3и потока...
т.е получается проверка нижней части списка сайтов ок, сверху не все подхватывает.. предполагаю что это из за количества потоков которые запускаю..
ЗЫ убрал критическую секцию результат тот же что и с ней, т.е КС не выполняет свою функцию..
Код:
var
 HTTP: TIdHTTP;
 i:Integer;
 cur:Integer;
begin
       while Acc<>ts.Count-1 do
              begin
   CS.Enter;
   Inc(Acc);
      cur:=  Acc  ;
   CS.Leave;

         HTTP:=TIdHTTP.create(nil);
    HTTP.HandleRedirects:=false;
       HTTP.ConnectTimeout:=300;
        HTTP.ReadTimeout:=300;
         try

      HTTP.Get('http://'+ts.Strings[cur]+'/status');
      if HTTP.ResponseText='HTTP/1.0 200 OK' then rez:=1 else rez:=0 ;
         Synchronize(Sync);
except
        rez:=0  ;
        Synchronize(Sync);
      end;
      //  dec(Thread);
      HTTP.Free;
  end;
end;

Последний раз редактировалось niva622; 17.03.2016 в 22:50.
niva622 вне форума Ответить с цитированием
Старый 18.03.2016, 09:59   #4
niva622
Форумчанин
 
Регистрация: 31.12.2006
Сообщений: 114
По умолчанию

А можно перенести в тему "Работа с сетью в Delphi" А то видимо ответа я не получу еще долго) Спасибо
niva622 вне форума Ответить с цитированием
Старый 18.03.2016, 10:05   #5
vlad1389
Форумчанин
 
Регистрация: 02.02.2016
Сообщений: 290
По умолчанию

Мы просматриваем темы через "новые сообщения". Нам без разницы, где оно размещено, главное что название было адекватное. Поэтому на скорость ответа перемещение ни как не повлияет.
vlad1389 вне форума Ответить с цитированием
Старый 18.03.2016, 10:08   #6
eoln
Старожил
 
Аватар для eoln
 
Регистрация: 26.04.2008
Сообщений: 2,689
По умолчанию

Цитата:
если к ответу серера добавить переменную cur или acc то начинается она с 4, т.к запускаю в 3и потока
Цитата:
ЗЫ убрал критическую секцию результат тот же что и с ней, т.е КС не выполняет свою функцию
критические секции объявлены в главном потоке(в самой главной программе)) )? Если нет, то толку от них нет
Цитата:
рабочий сервер с ответом 200 идет в список не рабочих
таймаут в 300 мс очень маленький.

Последний раз редактировалось eoln; 18.03.2016 в 10:10.
eoln вне форума Ответить с цитированием
Старый 18.03.2016, 10:47   #7
Pavia
Лис
Старожил
 
Аватар для Pavia
 
Регистрация: 18.09.2015
Сообщений: 2,409
По умолчанию

Для niva622
Цитата:
А можно перенести в тему "Работа с сетью в Delphi" А то видимо ответа я не получу еще долго) Спасибо
eoln уже всё написал. Не вижу ничего, что тут можно добавить.

О-нашёл:переменная rez - опять таки у вас не локальная. Вот и чехарда с результатом. Надо подумать над её синхронизацией, думаю тут лучше всего использовать SendMessage().


Цитата:
таймаут в 300 мс очень маленький.
Оз МО. До Москвы пинг 30-50 мс. До США пинг 150-250 мс. До Европы меньше. До Китая также как до США.
Достаточно много таких серверов которые с временем ответа около 0,5 секунды.

Так что выбор тайм-аута зависит от задачи, но 300 мс не чуть не хуже любой другой цифры. Всегда найдётся медленные сервера, которые не успевают ответить. А вообще максимальное время ответа в районе 60 с. Хотя обычный браузер уже через 10 секунд даст отказ.

ConnectTimeout надо сделать в 2 раза больше чем ReadTimeout. Так как в TCP используется двух этапное рукопожатие.

ReadTimeout=300
ConnectTimeout=600
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал .

Последний раз редактировалось Pavia; 18.03.2016 в 10:56.
Pavia вне форума Ответить с цитированием
Старый 18.03.2016, 10:51   #8
niva622
Форумчанин
 
Регистрация: 31.12.2006
Сообщений: 114
По умолчанию

Цитата:
rez - опять таки у вас не локальная
переменная rez у меня локальная, (насколько я понимаю) принадлежит она классу потока объявлена в
execute
private
rez:integer;

ЗЫ если что то неправильно говорю извините, самоучка..
Цитата:
критические секции объявлены в главном потоке(в самой главной программе))
да, критическая секция объявлена в самой главной программе (в глобальной переменной var) Создается при создании формы.
Еще вопрос а как лучше создать 3и потока ? я делаю это через цикл for..

Последний раз редактировалось niva622; 18.03.2016 в 11:26.
niva622 вне форума Ответить с цитированием
Старый 18.03.2016, 22:31   #9
niva622
Форумчанин
 
Регистрация: 31.12.2006
Сообщений: 114
По умолчанию

Хм ну спустя 2а дня все таки разобрался, вообщем смысл такой, решил выводить не одним списком рабочий/не рабочий, а создать 2а поля, в одно кидать рабочие сервера в другой нерабочие.. Видимо по другому в принципе не возможно, т.к потоки идут кучно.. и и по порядку их разложить не реально... Всем спасибо..
niva622 вне форума Ответить с цитированием
Старый 18.03.2016, 22:48   #10
vlad1389
Форумчанин
 
Регистрация: 02.02.2016
Сообщений: 290
По умолчанию

Цитата:
Видимо по другому в принципе не возможно
Возможно. Вы не верно организовали логику. Я так понимаю, проблема в том, что Вы запускаете потоки последовательно, и ждёте от них последовательного завершения, и это и есть ошибка, так как время действия каждого отдельно потока напрямую зависит от пинга, который как известно, прыгает. В таких случаях нужно опираться на входные данные при синхронизации, и тогда не будет перемешивания.
Кроме того в вашем коде имеется банально бесполезные вещи. Например
Код:
Inc(Acc);
Не имеет смысла, так как мы можем организовать количество потоков, равное количеству серверов. Каждый поток отработает один раз, и смысл считать выполнения отпадает.
Этот код
Код:
if HTTP.ResponseText='HTTP/1.0 200 OK' then tsg.add('+') else tsg.add('+') ;
Вообще бессмысленен. Можно просто написать
Код:
tsg.add('+') ;
И отработает одинаково.
vlad1389 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проверка сайтов на наличие слова на странице VitProff Работа с сетью в Delphi 12 11.10.2014 13:02
многопоточная сортировка в winapi Arrioh Помощь студентам 0 09.06.2013 23:40
Многопоточная загрузка RelictOs Общие вопросы Delphi 0 04.01.2013 14:52
многопоточная сортировка слиянием gagarin614 Помощь студентам 0 03.10.2012 16:03
Многопоточная программа kakawkin Общие вопросы Delphi 4 05.06.2011 00:33