Здравствуйте.
В процессе изучения anyevent::http столкнулся с проблемой.
Суть её опишу на примере.
Есть скрипт, который на вход принимает адрес интернет ресурса (ya.ru, например) далее скрипт берет массив прокси-серверов (который уже задан в коде) и выполняет цикл по элементам массива, подавая их в качестве параметров к запросу http_head:
1.
2.
3.
push @guards, http_head gen_uri($resource), proxy => [$host, $port, $schems], timeout => $time_sec , get_params($resource), sub
#где $resource содержит 'http://ya.ru', а $host, $port принимают значение полученные из массива прокси-серверов.
Так же в цикл передается устанавливаемое в коде скрипта значение тайм-аута.
Как только от http_head запроса приходит код 200, мы посылаем $cv->send(999) (999 просто число, в случае когда ответ 200 не пришел ни разу посылается 333) и выходим из функции в главное меню, где нам сново предлагают ввсести адрес ресурса.
И тут начинаются чудеса.
Предположим тайм-аут = 4, если ввести новый адрес более чем через 4 секунды, то http_head моментально вернет для всех (или для первых пяти-шести) запросов код 595.
Если же ввести менее чем через 4 секунды, то код отработает нормально.
Соответственно, если тайм-аут = 10, то нужно ждать 10 секунд, что бы получить неадекват.
Т.е. получается где-то в фоне скрипта сидит какой-то таймер, завязанный на значение тайм-аута, который не дохнет после выполнения всех http_head запросов (как в прочем и http_get, http_post и пр.) и при следующем вызове функции с этим http_head запросом игнорирует передаваемое значение тайм-аута, а берет какое-то своё.
Код скрипта:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
#!/usr/bin/perl
use strict;
use AnyEvent::HTTP;
use LWP::UserAgent;
use URI::UTF8::Punycode;
use Encode;
while (1)
{
print "\t\tMenu \n\n";
print "1. Enter url-address\n2. Quit.\n\nEnter menu item: ";
my $choise = <STDIN>; #выбор пункта меню
if ($choise != 1 && $choise != 2) #проверка на число от 1 до 3
{
print "Wrong number!\n";
redo;
}
if ($choise == 1)
{
printf "Enter url-address with out \'http://www.\': ";
my $host = <>;
if ($host !~ /\./g)
{
print "-!- Wrong url.\n";
redo;
}
substr($host, -1) = ''; #удаляем перенос строки
my @proxy_list = ('88.198.64.141:8118', '217.79.189.229:3128', '5.9.225.130:8080', '217.79.189.229:8080', '5.9.199.55:3129', '31.47.250.238:3128', '5.9.187.106:8080');
my $timeO=4;
while(1)
{
my ($res) = check_for_availability ($host, $timeO, \@proxy_list);
if ($res == 999)
{ print "ok\n"; last; }
else { print "bad\n"; last; }
}
}
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;
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); #если пришёл код 200, то возвращаем 999
}
$i++;
if ($i >= scalar @ip_port_list)
{
$i=0;
$cv->send(333);
}
};
}
$result = $cv->recv;
if($result == 999) #если пришёл код 200, то возвращаем 999
{
undef $_ for @guards; #что бы не принимать информацию от оставшихся http_head запросов удаляем объект guards
}
$time_sec = 0;
return ($result);
}
#---Генерация ссылки---------------------------------------------------------------------------
sub gen_uri
{
my $url = 'http://www.' . $_[0] ;
return $url;
}
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)',
'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1',
'Mozilla/5.0 (Windows; U; Windows NT 6.0; ru; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3',
];
#---Генерация параметров запроса---------------------------------------------------------------
sub get_params
{
%{{
cookie_jar => {},
headers => {
'Host' => $_[0],
'Referer' => 'http://' . $_[0] . '/',
'User-Agent' => $user_agents->[int rand @$user_agents],
},
}};
}
В догонку
Пример выполнения:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
user#userPC:~$ ./cin
Menu
1. Enter url-address
2. Quit.
Enter menu item: 1
Enter url-address with out 'http://www.': ya.ru
--- [1 :7] proxy: 88.198.64.141:8118 HTTP status code: 500
--- [2 :7] proxy: 5.9.225.130:8080 HTTP status code: 200
200
ok
Menu
1. Enter url-address
2. Quit.
ждем секунд 5 и вводим 1 и адрес:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Enter menu item: 1
Enter url-address with out 'http://www.': ya.ru
--- [1 :7] proxy: 88.198.64.141:8118 HTTP status code: 595
--- [2 :7] proxy: 217.79.189.229:3128 HTTP status code: 595
--- [3 :7] proxy: 5.9.225.130:8080 HTTP status code: 595
--- [4 :7] proxy: 217.79.189.229:8080 HTTP status code: 595
--- [5 :7] proxy: 5.9.187.106:8080 HTTP status code: 403
--- [6 :7] proxy: 5.9.199.55:3129 HTTP status code: 200
200
ok
Menu
1. Enter url-address
2. Quit.
Первые 4 запоса выскочили моментально.
Если теперь сразу ввести 1 и адрес то все отработает как надо:
1.
2.
3.
4.
5.
6.
Enter menu item: 1
Enter url-address with out 'http://www.': ya.ru
--- [1 :7] proxy: 217.79.189.229:3128 HTTP status code: 200
200
ok
Menu
Если же снова подождать 4-5 секунд, то ситуация повторится, тайм-аут заданные мною в коде не срабатывает.
Как с этим можно бороться?