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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> AnyEvent::DNS в работе AnyEvent::HTTP 
:(
    Опции темы
Aspire
Дата 20.5.2012, 12:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте, уважаемые гуру. Далее по тексту AE eq AnyEvent.
Подскажите, пожалуйста, каким образом мне можно включить асинхронный резольвинг доменов в паука написанного на AE::HTTP.
Вернее, не совсем асинхрон, просто хочу определить таймаут для днс запроса, потому как стандартный около 5 секунд сильно тормозит работу.
Предполагаю сделать это с помощью AE::DNS, включив его в коллбэк 
Код

tcp_connect => $callback->($host, $service, $connect_cb, $prepare_cb)
, который предусмотрен в AE::HTTP.
Однако я не понимаю как именно это сделать - переписывать все функцию AnyEvent::Socket::tcp_connect?
Или проще пропатчить процедуру resolve_sockaddr в пакете AnyEvent::Socket, которая вызывается из tcp_connect для резольвинга домена.
Этот путь мне кажется не верным, наверняка все проще, просто я чего-то не знаю.

Чтобы было более понятно, попробую изложить вышеописанный вопрос схематично:
Код

$cv->begin;
AE::HTTP::http_request GET => "$url", headers => {}, 
        tcp_connect => sub {
                # здесь нам нужно сделать асинхронный запрос днс с нужным таймаутом используя select из экземпла в доках AE::DNS
                # далее каким то образом передать полученный адрес в оригинальную ф-цию AE:::Socket::tcp_connect
                # или если это невозможно - переписать ее, но там можно голову сломать случайно
        }, 
        sub => {
                # здесь определены обычные действия, которые мы выполняем получив ответ HTTP сервера
                $cv->end; 
        }


Понятно, что мне совсем не понятен порядок действий в коллбеке tcp_connect.

Очень буду признателен всем за помощь и примеры.
PM MAIL   Вверх
Pfailed
Дата 20.5.2012, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Callback tcp_connect должен возвратить сокет и инициализировать соединение сокета.
Порядок действий примерно такой:
определяете где-то в начале скрипта объект AnyEvent::DNS с нужным таймаутом и другими параметрами, например можно подтюнить max_outstanding (по умолчанию всего 10 одновременных днс запроса)
в обратном вызове tcp_connect создаёте сокет и вызываете на нем prepare callback, он возвратит общий таймаут для запроса, и возможно подготовит сокет еще каким-либо образом
вызываете метод resolve ранее созданного объекта AnyEvent::DNS
в обратном вызове метода resolve делаете AnyEvent::Socket::tcp_connect с таймаутом, который возвратил prepare callback
в обратном вызове для AnyEvent::Socket::tcp_connect вызываете connect callback для первоначального обратного вызова tcp_connect
Плюс ко всему нужно учесть вариант, что какой-либо из вызовов возвратит ошибку.

Нечто похожее, но по другому я делал в AnyEvent::HTTP::Socks: https://github.com/olegwtf/p5-AnyEvent-HTTP...TP/Socks.pm#L73
Но там я использовал таймер для таймаута, плюс не было цели делать таймаут именно для днс запроса.



--------------------
PM MAIL   Вверх
Pfailed
Дата 20.5.2012, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Кстати я заглянул в документацию AnyEvent::DNS. Там есть глобальный резолвер $AnyEvent::DNS::RESOLVER, который можно определить нужным образом. Так что всё вышеописанное является лишним.


--------------------
PM MAIL   Вверх
Aspire
Дата 20.5.2012, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Глобальный все упрощает )
Однако, позвольте уточнить первый вариант, для меня это будет незаменимым опытом.

Код

my $resolver = new AnyEvent::DNS timeout => 1; # определяете где-то в начале скрипта объект AnyEvent::DNS с нужным таймаутом ...

$cv->begin;
AE::HTTP::http_request GET => "$url", headers => {}, 
        tcp_connect => sub {
                my $sk; # в обратном вызове tcp_connect создаёте сокет ... 
                socket ($sk, PF_INET, SOCK_STREAM, getprotobyname ('tcp')); # опустим препаре-коллбэк, для упрощения
                $resolver->resolve ('google.com', 'a', sub {  # в обратном вызове метода resolve делаете AnyEvent::Socket::tcp_connect
                                AnyEvent::Socket::tcp_connect 173.194.32.1, 80, # делаете AnyEvent::Socket::tcp_connect
                                ... # тут я потерялся уже в коллбеках
                                sub {} # ну или это не важно, т.к. адрес уже известен?
                                # а как быть если адреса нет.. что возвращать?
                };
        }, 
        sub => {
                # здесь определены обычные действия, которые мы выполняем получив ответ HTTP сервера
                $cv->end; 
        }


Это сообщение отредактировал(а) Aspire - 20.5.2012, 17:25
PM MAIL   Вверх
Aspire
Дата 20.5.2012, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Стоп.. что-то лишнее. Сокет вроде smile
PM MAIL   Вверх
Pfailed
Дата 20.5.2012, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Немного неправильно я вам рассказал. В частности, о том что должен возвратиться сокет из функции. А если он не должен возвращаться, значит и создавать его не нужно вручную. В итоге получилось следующее

Код

use strict;
use warnings;
use AnyEvent::HTTP;
use AnyEvent::DNS;
use AnyEvent::Socket;

my $cv = AE::cv;
my $resolver = AnyEvent::DNS->new(timeout => [1], max_outstanding => 50); # создаём резолвер с нужными параметрами
$resolver->os_config(); # подхватываем системные настройки DNS

http_get 'http://google.ru', timeout => 30, tcp_connect => sub {
    my ($host, $service, $connect_cb, $prepare_cb) = @_;
    
    $resolver->resolve($host, 'a', sub { # делаем днс запрос
        return $connect_cb->() unless @_; # получили ошибку днс
        my $ip = pop @{$_[0]}; # берем первый пришедший ip (может прийти несколько)
        
        tcp_connect $ip, $service, sub { # делаем коннект уже по ip, а не хостнейму
            $connect_cb->(@_); # передаем управление AnyEvent::HTTP
        }, sub {
            $prepare_cb->(shift); # устанавливаем нужный таймаут для коннекта (30 сек в данном случае)
        };
    });
    
    $connect_cb; # должны вернуть объект оберегающий соединение (объект который не удаляется пока идет connect), вроде этот подходит
    
},sub {
    my ($body, $headers) = @_;
    print $headers->{Status}, "\n";
    print $body;
    $cv->send;
};

$cv->recv;



--------------------
PM MAIL   Вверх
Aspire
Дата 20.5.2012, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Pfailed, огромнейший респект.
Спасибо, что помогли разобраться в сложном для меня вопросе.

Плюсанул бы, но не хватает прав.
PM MAIL   Вверх
JackYF
Дата 23.5.2012, 23:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

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



Цитата(Aspire @  20.5.2012,  18:09 Найти цитируемый пост)
Плюсанул бы, но не хватает прав. 

Сделано. Да, кстати, пометьте тему как решённую.


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Aspire
Дата 31.5.2012, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Ну вот дошла очередь потестить на линуксах.. и оказалось, что днс таймаут там попросту не работает (на виндах все работает на ура, не нарадуюсь просто).

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


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

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


 




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


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

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