2009-10-02 6 views
1

J'essaie de me connecter à un service Web en utilisant IO :: Socket :: INET (oui, je sais qu'il y a beaucoup de meilleurs modules pour cela, mais je ne sais pas Je les ai et je ne peux pas les ajouter, alors ne le suggérez pas), mais je pars (je pense que c'est ce qu'il fait) attendre une réponse.IO :: Délai d'attente lors de l'obtention de la réponse

est ici le point crucial de base de mon code (je remplir préalablement le contenu avec tous les en-têtes appropriés, et mis en place, etc.):

$httpSock->print($content); 

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

Il semble que ma demande est faite immédiatement, il attend environ 2 minutes avant de cracher la réponse. Si je modifie le code pour utiliser une socket raw recv au lieu de getlines(), ala:

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

Je reçois immédiatement la réponse (bien que seuls les 1024 premiers caractères). Est-ce que je fais quelque chose de mal ici? J'utilise une version assez tardive de IO :: Socket que autoflushdevrait être activé par défaut, mais l'allumer explicitement ne semble pas faire de différence. Je pourrais probablement aussi continuer à lire à partir de la socket jusqu'à ce que je reçois la réponse entière, mais c'est certainement plus désordonné que d'utiliser getlines() ou <$httpSock>.

Merci d'avance.

Répondre

3

Je rencontre un problème lors de la recréation du problème avec l'extrait de code que vous avez publié. Voici le code je l'ai testé avec:

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; 
} 

Voici les résultats:

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

real 0m0.084s 
user 0m0.025s 
sys 0m0.007s 
+1

Oui, c'est assez proche de ce que j'ai. Une enquête plus approfondie me porte à croire que c'est une question d'EOF d'une certaine sorte. Si j'utilise 'getline()' (dans une boucle), il saisit tout sauf la dernière ligne. Si j'utilise 'recv()' il recevra toutes les données sauf le dernier bit. Est-ce que cela vous aide? – Morinar

+0

Je suis également en train d'effectuer un POST plutôt qu'un HEAD ou un GET. Je ne sais pas si cela fait une différence ... – Morinar

+0

Votre exemple fonctionne également pour moi, mais si vous changez HTTP/1.0 en HTTP/1.1 (ce que j'utilisais) votre exemple se bloque comme le mien. Quelle est la différence entre HTML/1.0 et HTML/1.1? – Morinar

3

Le problème est que getlines() attend jusqu'à ce que la connexion est fermée. Si le service Web auquel vous vous connectez ne ferme pas votre connexion, la fonction getlines attendra, pensant que plus de données sont en route. Lorsque votre connexion expire après ces 2 minutes environ, getlines voit la connexion se fermer et renvoie les lignes qu'il a reçues. D'un autre côté, Recv saisira tout jusqu'à la limite prédéterminée qui est sur la connexion à ce moment-là et la renverra au tampon que vous remettez immédiatement, mais il attendra jusqu'à ce qu'il obtienne des données s'il n'y en a pas actuellement. Je sais que vous pensez que le désordre, mais cela pourrait fonctionner pour vous:

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

Le MSG_DONTWAIT fera recv de ne pas attendre un message si la connexion est vide. Vous pouvez également augmenter 1024 à un grand nombre pour diminuer le nombre de boucles, ou même éventuellement obtenir le message entier à la fois.

Ceci devrait également vous permettre de garder les prises ouvertes pour une utilisation ultérieure jusqu'à ce que vous les fermiez vous-même. Je me demande si l'exemple google fonctionne parce que google.com ferme la connexion après qu'elle a répondu.

+0

Quelques bonnes pensées là-dedans, mais s'il vous plaît voir mes commentaires dans l'autre réponse pour le "vrai" problème/solution. – Morinar

Questions connexes