【问题标题】:Perl socket connection hangs on external hostPerl 套接字连接在外部主机上挂起
【发布时间】:2018-04-15 01:32:25
【问题描述】:

我有下面的程序,它建立一个套接字连接并读回服务器返回的第一行。它适用于我网络内的任何东西,但如果我试图走出去,它只会挂起并且不做任何事情。即端口25上的smtp.gmail.com。不知道有什么问题,谷歌搜索并没有给我太多。

use Socket;
use Net::Ping;

$remote = $ARGV[0];
$port = $ARGV[1];

my $p = Net::Ping->new();
if (!$p->ping($remote)) {
    print STDERR "Error: Invalid hostname\n";
    exit(1);
}

if ($port =~ /\D/) {
    $port = getservbyname($port, 'tcp')
}
if ($port > 65535 || $port < 0) {
    print STDERR "Error: Invalid port\n";
    exit(1);
}
$iaddr = inet_aton($remote);
$paddr = sockaddr_in($port, $iaddr);
$proto = getprotobyname('tcp');
socket(SOCK, PF_INET, SOCK_STREAM, $proto);
connect(SOCK, $paddr);
$line = <SOCK>;
print STDOUT "$line\n";
close(SOCK);

exit(0);

任何帮助将不胜感激。

【问题讨论】:

  • 始终使用use strict; use warnings qw( all );!!!

标签: perl sockets freeze


【解决方案1】:

您的代码并没有什么问题,只是您有错误的假设。

您的假设是Net::Ping 可用于确定主机是否有效,但这种假设是错误的。 Net::Ping 默认情况下只是尝试向主机发送 ICMP 回显请求并期望返回 ICMP 回显响应。但是许多主机(如smtp.gmail.com)不会回复此类请求,即使该主机可能可以通过其他方式访问,例如通过 TCP 连接到特定端口,就像您接下来所做的那样。

我只是建议删除Net::Ping 的这种用法。如果无法连接到主机,则connect 将失败,这应该足够了。但是即使connect 成功,您的代码也可能会挂起,因为您依赖服务器首先发送一些数据。在 SMTP(端口 25)或 FTP(端口 21)等协议中,服务器将首先发送一些问候语,但在 HTTP(端口 80)等其他协议中,客户端应在服务器回复之前发送数据。在这些情况下,您的代码将挂起,因为它不发送任何数据,因此服务器只是挂起等待正确的请求,然后再发送响应。

除此之外,我建议使用IO::Socket::IP 而不是普通的套接字。它不仅使代码更简单,而且还可以透明地与 IPv6 一起使用。您的代码明确使用了inet_aton,因此仅适用于 IPv4。

【讨论】:

    猜你喜欢
    • 2011-01-19
    • 2019-10-14
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    • 2012-03-12
    • 2014-09-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多