2009-10-02 2 views
1

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

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

$httpSock->print($content); 

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

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

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

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

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

ответ

3

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

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 
+1

Да, это очень близко к тому, что у меня есть. Дальнейшее исследование заставляет меня поверить, что это вопрос EOF. Если я использую 'getline()' (в цикле), он захватывает все, кроме последней строки. Если я использую 'recv()', он получит все данные, кроме последнего бита. Это вообще помогает? – Morinar

+0

Я также выполняю POST, а не HEAD или GET. Не уверен, что это имеет значение ... – Morinar

+0

Ваш пример также работает для меня, однако, если вы меняете HTTP/1.0 на HTTP/1.1 (это то, что я использую), ваш пример зависает так же, как и мой. В чем разница между HTML/1.0 и HTML/1.1? – Morinar

3

Проблема заключается в том, что 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 закрывает соединение после его ответа.

+0

Некоторые хорошие мысли там, но, пожалуйста, посмотрите мои комментарии в другом ответе на «настоящую» проблему/решение. – Morinar

Смежные вопросы