2009-10-02 85 views
1

我试图使用IO :: Socket :: INET连接到Web服务(是的,我知道有很多更好的模块可以做到这一点,没有它们,不能添加它们,所以请不要提示它),但是我正在等待(等待响应)。IO :: Socket获取响应时超时

这里是我的代码的基本症结(我以前填充所有适当的标题的内容,并对其进行设置等):

$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 2009-10-02 18:22:09

+0

我也在执行POST而不是HEAD或GET。不知道这是否有什么区别... – Morinar 2009-10-02 18:26:32

+0

您的示例也适用于我,但是如果您将HTTP/1.0更改为HTTP/1.1(这是我使用的),您的示例与我的一样挂起。 HTML/1.0和HTML/1.1有什么区别? – Morinar 2009-10-02 18:43:24

3

的问题是,getlines()等待,直到连接被关闭。如果您连接的Web服务没有关闭连接,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.com是响应后关闭连接。

+0

那里有一些很好的想法,但请参阅我对“真正”问题/解决方案的其他答案的评论。 – Morinar 2009-10-02 21:06:08