IO :: Время ожидания сокета при получении ответа - PullRequest
1 голос
/ 02 октября 2009

Я пытаюсь подключиться к веб-сервису, используя IO :: Socket :: INET (да, я знаю, что для этого есть много лучших модулей, но у меня их нет и я не могу их добавить , поэтому, пожалуйста, не предлагайте это), но я ожидаю ответа (я думаю, что это именно то, что он делает).

Вот основная суть моего кода (я ранее заполнял содержимое всеми соответствующими заголовками, настраивал его и т. Д.):

$httpSock->print($content);

my @lines = $httpSock->getlines();
foreach my $line ( @lines ) {
    print $line;
}

Похоже, что мой запрос сделан немедленно, затем он ждет около 2 минут, прежде чем выложить ответ. Если я изменю код для использования необработанного сокета recv вместо getlines(), ala:

$httpSock->recv($data, 1024);

Я получаю ответ немедленно (хотя только первые 1024 символа). Я что-то здесь не так делаю? Я использую достаточно позднюю версию IO :: Socket, чтобы autoflush должен был быть включен по умолчанию, но его включение явно не имело никакого значения. Возможно, я мог бы просто продолжать читать из сокета, пока не получу полный ответ, но это определенно более грязно, чем использование getlines() или <$httpSock>.

Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 03 октября 2009

Проблема в том, что getlines () ждет, пока соединение не будет закрыто. Если веб-служба, к которой вы подключаетесь, не закрывает ваше соединение, функция getlines будет ждать, ожидая получения дополнительных данных. Когда ваше соединение истекает примерно через 2 минуты или около того, getlines видит закрытие соединения и возвращает вам полученные линии. Recv, с другой стороны, будет захватывать все до заданного предела, который находится на соединении в то время, и немедленно возвращать его в буфер, который вы передаете, но он будет ждать, пока не получит некоторые данные, если в настоящее время их нет. Я знаю, вы думаете, что это грязно, но это может сработать для вас:

$httpSock->recv($buf, 1024);
$message = "";
while (length($buf) > 0) {
    $message .= $buf;
    $httpSock->recv($buf, 1024, MSG_DONTWAIT);
}
print $message;

MSG_DONTWAIT приведет к тому, что recv не будет ждать сообщения, если соединение пустое. Вы также можете увеличить 1024 до некоторого большого числа, чтобы уменьшить количество циклов, или даже, возможно, даже получить все сообщение сразу.

Это также позволит вам держать розетки открытыми для дальнейшего использования, пока вы сами не закроете их.

Мне интересно, работает ли пример Google, потому что google.com закрывает соединение после ответа.

3 голосов
/ 02 октября 2009

У меня проблема с воссозданием проблемы с фрагментом кода, который вы разместили. Вот код, который я тестировал:

use strict;
use warnings;
use IO::Socket;

my $httpSock = new IO::Socket::INET(
    PeerAddr => 'www.google.com',
    PeerPort => '80',
    Proto    => 'tcp',
);

my $content = "HEAD / HTTP/1.0\r\nHost: www.google.com\r\n\r\n";

$httpSock->print($content);
my @lines = $httpSock->getlines();
foreach my $line (@lines) {
    print $line;
}

Вот результаты:

$ time ./1.pl
HTTP/1.0 200 OK
-snip-  

real    0m0.084s
user    0m0.025s
sys 0m0.007s
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...