Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Anyevent::HTTP, как не дожидаться ответа get запроса 
:(
    Опции темы
HeinzFelfe
  Дата 6.12.2012, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 15.9.2012

Репутация: нет
Всего: нет



Преступил к изучению anyevent::http.
Возникают вопросы, может кто сталкивался с подобным уже.

И так, в предпологаемой программе берется спискок прокси-серверов (пусть их там будет 1000 штук), и по каждому из них, через цикл, выполняется get запрос.
Необходимо при получении кода состояния HTTP '200 ok' выходить из цикла и не дожидаться ответа от уже посланных запросов.

Как это сделать я не понмаю.

У меня получается так: приходит ответ 200 ok, вызываю $cv->cend, но цикл продолжает выполняться. 
использовать exit нельзя, т.к. мы должны остаться в программе. 
return так же не работает.

Как быть?

p.s. в английском не силён, так что чтение мануалов официальных весьма затруднено...

Это сообщение отредактировал(а) HeinzFelfe - 6.12.2012, 18:07
PM MAIL   Вверх
DurRandir
Дата 6.12.2012, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 1
Всего: 17



Цитата(HeinzFelfe @ 6.12.2012,  19:01)
p.s. в английском не силён, так что чтение мануалов официальных весьма затруднено...

Увы, но вся документация будет только на cpan и только на английском. Вот нужный кусок документации:

When called in void context, nothing is returned. In other contexts, http_request returns a "cancellation guard" - you have to keep the object at least alive until the callback get called. If the object gets destroyed before the callback is called, the request will be cancelled.
PM   Вверх
HeinzFelfe
Дата 6.12.2012, 18:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 15.9.2012

Репутация: нет
Всего: нет



Цитата(DurRandir @ 6.12.2012,  18:13)
If the object gets destroyed before the callback is called, the request will be cancelled.

Можете пояснить о каком объекте идет речь?
PM MAIL   Вверх
HeinzFelfe
Дата 6.12.2012, 19:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 15.9.2012

Репутация: нет
Всего: нет



Возможно я не корректно задал вопрос, может пример с конкретным кодом поможет.

прокси должны лежать в файле log.txt

вот для примера список прокси-серверов США:
74.112.203.107:3128
67.208.247.132:3128
96.47.230.49:8080
96.47.230.49:3128
74.221.211.117:8080
198.154.114.100:8080
173.213.113.211:3128
192.211.49.210:3128
198.144.176.54:8080
199.119.76.111:3128
74.112.203.107:8080
74.94.44.210:8080
198.144.176.54:3128
199.119.76.111:8080
74.221.211.117:3128
173.242.117.146:8080
173.213.113.211:8080
173.242.117.146:3128
198.154.114.100:3128
192.211.49.210:8080



Код

#!/usr/bin/perl 
use strict;
use AnyEvent::HTTP;

$AnyEvent::HTTP::MAX_PER_HOST=100;

my $user_agents = [
    'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/0.4.154.25 Safari/525.19',
    'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
    'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50215) Netscape/8.0.1',
    'Opera/9.50 (Windows NT 5.1; U; ru)',   
];

while (1)
{
    print "\t\tMenu \n\n1. Enter url-address\n2. Quit.\n\nEnter menu item: ";
    my $choise =  <STDIN>; #выбор пункта меню
    if ($choise != 1 && $choise != 2) #проверка на число от 1 до 2
    { 
        print "Wrong number!\n";
        redo;
    } 
    if ($choise == 1)
    {
        printf "Enter url-address with out \'http://www.\': ";
        my $host = <STDIN>;    
        substr($host, -1) = ''; #удаляем перенос строки        
        my @proxy_list = get_ip_port_list();
        my ($res) = check_for_availability ($host, 10, \@proxy_list); #передаем имя хоста к которому будем делать гет запрос и список проксей
        if ($res == 999) { print "ok\n"; }                                            #если check_for_availability вернула 999, то значит получен код 200
        else                  { print "bad\n"; }                                  #в этом случаее код 200 не получен
    }
    if ($choise == 2)
    {
        print "\t\tGood bye...\n\n";
        exit;
    }    
}


sub check_for_availability ()
{    
    my $resource = $_[0];
    my $time_sec = $_[1]; 
    my ($link_arr) = $_[2];
    my @ip_port_list   =  @$link_arr;
    my $cv = AnyEvent->condvar;
    my $schems = 'http';
    my $result;    
    my $i=0;
        
    for (my $j = 0; $j < scalar @ip_port_list; $j++)   #цикл по списку проксей
    {
        my $element = $ip_port_list[$j];
        my @temp = $element =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/g;
        my $host = $temp[0];
        @temp = $element =~ /:\d{1,5}/g;
        my $port = substr($temp[0], 1);
        http_head gen_uri($resource),  proxy => [$host, $port, $schems], timeout => $time_sec, get_params($resource), sub  
        {    
            my ($page , $hr) = @_;
            printf "--- [%-4d:%d]  proxy: %-21s HTTP status code: %-3d\n",  $i+1, scalar @ip_port_list, $element, $hr->{Status};
            if ($hr->{'Status'} == 200 )
            {
                print "200\n";
                $cv->send(999);
            }          
            $i++; 
            if ($i >= scalar @ip_port_list)
            {
                $i=0;
                $cv->send(333);
            }
        };    
    }
    $result = $cv->recv;
    return ($result);
}


sub gen_uri 
{
    my $url = 'http://www.' . $_[0] ;
    return $url;
}

sub get_params
{
    %{{
        cookie_jar => {},
        headers    => {
            'Host'    =>  $_[0],
            'Referer' => 'http://' . $_[0] . '/',
            'User-Agent' => $user_agents->[int rand @$user_agents],
        },
    }};
}

sub get_ip_port_list
{
    my $origfile = 'log.txt';
    #my $origfile = 'all_proxy';
    my %hTmp;
    my @ip_port;
    my $i=0;
    open (IN, "<$origfile") or die "Couldn't open input file: $!";
    while (my $sLine = <IN>) 
    {
        next if $sLine =~ m/^\s*$/; #remove empty lines
        unless ($hTmp{$sLine}++)
        {
            if($sLine =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}/)
            {
                substr($sLine, -1) = '';
                $ip_port[$i] = $sLine;
                $i++;
            }            
        }
    }
    close IN;
    return @ip_port;
}


Если запустить скрипт первый раз, и задать какой-нибудь хост, ya.ru, например, то все отрабоатет нормально, но если после этого снова задать какой-нибудь хост, то сначала будут выведены результыта из прошлого запуска. Что бы было понятней вот пример запуска:

Код

user@userPC:~$ ./cin
        Menu 

1. Enter url-address
2. Quit.

Enter menu item: 1
Enter url-address with out 'http://www.': google.com
--- [1   :20]  proxy: 74.94.44.210:8080     HTTP status code: 407
--- [2   :20]  proxy: 96.47.230.49:8080     HTTP status code: 200
200
ok
        Menu 

1. Enter url-address
2. Quit.

Enter menu item: 1
Enter url-address with out 'http://www.': google.com
--- [3   :20]  proxy: 67.208.247.132:3128   HTTP status code: 200
200
--- [4   :20]  proxy: 96.47.230.49:3128     HTTP status code: 200
200
--- [5   :20]  proxy: 173.213.113.211:3128  HTTP status code: 200
200
--- [6   :20]  proxy: 173.213.113.211:8080  HTTP status code: 200
200
--- [1   :20]  proxy: 67.208.247.132:3128   HTTP status code: 407
--- [2   :20]  proxy: 74.112.203.107:3128   HTTP status code: 200
200
ok
        Menu 

1. Enter url-address
2. Quit.

Enter menu item: 



т.е. в первом запуске он получил ответ 200 для некоторого прокси-адреса (от которого быстрее ответ пришёл) а остальные 18 штук выведины не были:
Код

Enter url-address with out 'http://www.': google.com
--- [1   :20]  proxy: 74.94.44.210:8080     HTTP status code: 407
--- [2   :20]  proxy: 96.47.230.49:8080     HTTP status code: 200
200
ok

И при повторном вводе google.com, он сначала выводит 4 результата (начиная с 3 и до 6)  (видимо до прихода статуса 200 успел сделать всего 6 запрсов) из прошлого вызова, и только оптом начинает выводит результаты для нового запроса:
Код

Enter url-address with out 'http://www.': google.com
--- [3   :20]  proxy: 67.208.247.132:3128   HTTP status code: 200
200
--- [4   :20]  proxy: 96.47.230.49:3128     HTTP status code: 200
200
--- [5   :20]  proxy: 173.213.113.211:3128  HTTP status code: 200
200
--- [6   :20]  proxy: 173.213.113.211:8080  HTTP status code: 200
200
--- [1   :20]  proxy: 67.208.247.132:3128   HTTP status code: 407
--- [2   :20]  proxy: 74.112.203.107:3128   HTTP status code: 200
200
ok
        Menu 


Добавлено через 7 минут и 24 секунды
Вот как мне сбросить остальные запросы, которые послались параллельно с запросом от котрого получен статус 200?

Это сообщение отредактировал(а) HeinzFelfe - 6.12.2012, 19:14
PM MAIL   Вверх
HeinzFelfe
Дата 6.12.2012, 19:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 15.9.2012

Репутация: нет
Всего: нет



Так, что-то начинает прояснятся в голове.
Получается, что вот эти запросы из первого запуска, они уже выполнены, т.е.  что успело запросится и вернуться ответ, то и выводится ни каких лишних запросов из первого вызова не выполняется.
Осталось понять как их можно заставить не выводиться.
PM MAIL   Вверх
DurRandir
Дата 7.12.2012, 01:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 1
Всего: 17



Что-то в духе
Код

sub check_for_availability ()
{    
    my $resource = $_[0];
    my $time_sec = $_[1]; 
    my ($link_arr) = $_[2];
    my @ip_port_list   =  @$link_arr;
    my $cv = AnyEvent->condvar;
    my $schems = 'http';
    my $result;    
    my $i=0;
    my @guards;
        
    for (my $j = 0; $j < scalar @ip_port_list; $j++)   #цикл по списку проксей
    {
        my $element = $ip_port_list[$j];
        my @temp = $element =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/g;
        my $host = $temp[0];
        @temp = $element =~ /:\d{1,5}/g;
        my $port = substr($temp[0], 1);
        push @guards, http_head gen_uri($resource),  proxy => [$host, $port, $schems], timeout => $time_sec, get_params($resource), sub  
        {    
            my ($page , $hr) = @_;
            printf "--- [%-4d:%d]  proxy: %-21s HTTP status code: %-3d\n",  $i+1, scalar @ip_port_list, $element, $hr->{Status};
            if ($hr->{'Status'} == 200 )
            {
                print "200\n";
                $cv->send(999);
            }          
            $i++; 
            if ($i >= scalar @ip_port_list)
            {
                $i=0;
                $cv->send(333);
            }
        };    
    }
    $result = $cv->recv;
    undef $_ for @guards;
    return ($result);
}


PS: объект - это тот, который вернёт вызов http_*
PPS: Подумав ещё. Не очень красивый код для определения условия "всё пропало". Посмотрите кусок документации http://search.cpan.org/~mlehmann/AnyEvent-...S_FOR_PRODUCERS, в части $cv->begin, про AND/OR.

Это сообщение отредактировал(а) DurRandir - 7.12.2012, 01:25
PM   Вверх
HeinzFelfe
Дата 7.12.2012, 02:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 15.9.2012

Репутация: нет
Всего: нет



Цитата(DurRandir @ 7.12.2012,  01:14)
PS: объект - это тот, который вернёт вызов http_*
PPS: Подумав ещё. Не очень красивый код для определения условия "всё пропало". 

Да, за код извиняюсь, писал на скорую руку, для демонстрации наглядной.
Спасибо за ответы и ссылки (и за места где именно копать в них)).

Кстати, в приведенном вами коде появляется странная особенность.
Покажу на примере:
Запускаем скрипт
Код

user@userPC:~$ ./cin

____________________________________________
        Menu 

1. Enter url-address
2. Quit.

Enter menu item: 1

Enter url-address with out 'http://www.': ya.ru
--- Time out for http request: 10

--- [1   :5]  proxy: 85.15.203.1:8080      HTTP status code: 200 
200
ok
____________________________________________
        Menu 

1. Enter url-address
2. Quit.

Enter menu item: 
 

Если подождать, и не вводить сразу данные для следующей итерации, а ввести их секунд через 10, то вылезет вот такая штука, причем в один момент, без задержек

Код

Enter menu item: 1

Enter url-address with out 'http://www.': ya.ru
--- Time out for http request: 10

--- [1   :5]  proxy: 85.15.203.1:8080      HTTP status code: 596 
--- [2   :5]  proxy: 77.38.171.87:8080     HTTP status code: 595 
--- [3   :5]  proxy: 80.90.27.60:8080      HTTP status code: 595 
--- [4   :5]  proxy: 80.90.12.36:8080      HTTP status code: 595 
--- [5   :5]  proxy: 83.136.137.129:8080   HTTP status code: 595 
bad
____________________________________________
        Menu 

1. Enter url-address
2. Quit.

Enter menu item: 


Причем есть прямая зависимость от величены таймаута
Код

my ($res) = check_for_availability ($host, 10, \@proxy_list); 


Чем он меньше, тем меньше нужно жадть. 
Т.е. получается, в то время как программа ожидает ввод данных (новго адреса) где-то на фоне тикает тайм-аут, который в итоге может полностью истеч.
Как такое может быть? И как с этим бороться?


p.s. время ожидания, что бы вывелся на экран такой фокус, вроде как полностью совпадает с заданным тайм-аутом.
p.p.s. проблема с неостанавливающимся таймером была и раньше как выяснилось. Т.е. и до введения переменной @guards и её очистки.
Но как тогда задавать тайм-аут? Как добиться прекращения его истечения уже после выхода из колбэка... 

Это сообщение отредактировал(а) HeinzFelfe - 7.12.2012, 12:47
PM MAIL   Вверх
HeinzFelfe
Дата 7.12.2012, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 15.9.2012

Репутация: нет
Всего: нет



новые подробности.
Если изменить значение $AnyEvent::HTTP::MAX_PER_HOST=100; на стандартное 4
то результат 595 будет возвращаться только для первых 4 адресов.


Т.е. код 595 приходит только для первой партии запросов и если $AnyEvent::HTTP::MAX_PER_HOST=100 то для первой сотни всегда будет приходит значение 595.

Как с этим бороться по прежнему неясно.

Это сообщение отредактировал(а) HeinzFelfe - 7.12.2012, 19:29
PM MAIL   Вверх
HeinzFelfe
Дата 7.12.2012, 20:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 15.9.2012

Репутация: нет
Всего: нет



Расследование продолжается.
При убирании из запроса информации о прокси, ошибка пропадает.
Все дело в них, проксюшах, но вот в чем конкретно не ясно.
595 - errors during connection etsbalishment, proxy handshake - мало о чем мне говорит.

Это сообщение отредактировал(а) HeinzFelfe - 7.12.2012, 20:14
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: CGI программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к CGI программированию
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", качать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: разработка для Web | Следующая тема »


 




[ Время генерации скрипта: 0.0505 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.