IO::Socket 获取响应时超时

发布于 2024-08-06 01:00:04 字数 683 浏览 1 评论 0原文

我正在尝试使用 IO::Socket::INET 连接到 Web 服务(是的,我知道有很多更好的模块可以执行此操作,但我没有它们并且无法添加它们,所以请不建议这样做),但我正在等待回复(我认为这就是它正在做的事情)。

这是我的代码的基本关键点(我之前使用所有正确的标头填充内容,并进行设置等):

$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> 更混乱。

提前致谢。

I'm trying to connect to a web service using IO::Socket::INET (yes, I know that there are lots of better modules for doing this, but I don't have them and can't add them, so please don't suggest it), but I'm timing out (I think that's what it's doing) waiting for a response.

Here's the basic crux of my code (I previously populate the content with all the proper headers, and set it up, etc):

$httpSock->print($content);

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

It appears that my request is made immediately, then it waits about 2 minutes before spitting back the response. If I alter the code to use a raw socket recv instead of getlines(), ala:

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

I get the response immediately (although only the first 1024 chars). Am I doing something wrong here? I'm using a late enough version of IO::Socket that autoflush should be enabled by default, but turning it on explicitly didn't seem to make any difference. I could probably also just keep reading from the socket until I got the entire response, but that's definitely messier than using getlines() or <$httpSock>.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深白境迁sunset 2024-08-13 01:00:04

我在使用您发布的代码片段重新创建问题时遇到问题。这是我测试的代码:

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

I'm having an issue re-creating the problem with the code snippet you've posted. Here's the code I tested with:

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

Here are the results:

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

real    0m0.084s
user    0m0.025s
sys 0m0.007s
感性不性感 2024-08-13 01:00:04

问题是 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 在响应后正在关闭连接。

The problem is that getlines() waits until the connection is closed. If the web service you are connecting to doesn't close your connection, the getlines function will wait, thinking more data is on the way. When your connection times out after those 2 minutes or so, getlines is seeing the connection close, and returning the lines it received to you. Recv on the other hand will grab everything up to the predetermined limit that is on the connection at that time and return it to the buffer you hand it immediately, but it will wait until it gets some data if there is none currently. I know you think its messy, but this might work out for you:

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

The MSG_DONTWAIT will cause recv to not wait for a message if the connection is empty. You can also increase 1024 to some big number to decrease the number of loops, or even possibly even get the whole message at once.

This should also let you keep the sockets open for further use until you close it yourself.

I am wondering if the google example works because google.com is closing the connection after it responds.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文