我正在尝试使用IO :: Socket :: INET连接到Web服务(是的,我知道有很多更好的模块用于执行此操作,但我没有它们并且无法添加它们,所以请不要建议),但我已经超时(我认为这就是它在做什么)等待回复。
这是我的代码的基本关键(我之前使用所有正确的标题填充内容,并设置它等):
$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>
更麻烦。
提前致谢。
答案 0 :(得分: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 :(得分: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示例是否有效,因为google.com在响应后正在关闭连接。