我有以下程序进行套接字连接,只读回服务器返回的第一行。它适用于我网络中的任何内容,但如果我尝试去外面,它只会挂起而不会做任何事情。即smtp.gmail.com
端口25
。不确定它有什么问题,谷歌搜索并没有给我太多。
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);
任何帮助都将不胜感激。
答案 0 :(得分:3)
你的代码没有什么问题,你只是错误的假设。
您的假设是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。