我需要检查是否打开了远程UDP端口。我的代码部分是:
sub scanUDP {
my $address = shift;
my $port = shift;
my $udpSocket = new IO::Socket::INET (
PeerAddr => $address,
PeerPort => $port,
Proto => 'udp',
) or return 0;
$udpSocket -> send ('hello', 0);
#........SOME CODE.............
return 1;
}
..SOME CODE..
应检查我是否收到ICMP数据包“Host unreached”或“Port unreached”以检查端口是否已打开。但是我怎么能这样做呢?
答案 0 :(得分:1)
如果你真的得到一个ICMP无法访问,你将收到一个稍后发送调用的错误(除非你的peer是localhost,你可能已经得到了第一个)。但是无法保证您将无法访问ICMP,因为ICMP或UDP本身可能会被防火墙过滤掉。
看起来它不会以这种方式报告Windows上的问题,但你可以使用recv而不是send(也适用于UNIX)。错误代码可能是Windows特有的,ECONNREFUSED仅适用于UNIX:
use strict;
use warnings;
use IO::Socket::INET;
my $cl = IO::Socket::INET->new(
PeerAddr => '192.168.122.42:12345', # definitly rejecting
Proto => 'udp',
);
$cl->send('foo') or die "send failed: $!"; # first send will succeed
# wait some time to receive ICMP unreachable
sleep(1);
$cl->blocking(0);
if ( ! $cl->recv( my $buf,0)) {
# will get ECONNREFUSED on UNIX, on Win the code is different
warn "error $!" if ! $!{EAGAIN};
}
答案 1 :(得分:1)
一般情况下你不能。 UDP没有连接状态,因此不需要向您发送对您发送的数据包的任何回复。甚至在忽略包装丢失时也是如此。如果您以任何协议发送有效请求并且远程端口已打开,您可能会收到肯定答复,但不能使用此类答复作出任何结论。
答案 2 :(得分:1)
这是适用于我的代码:
sub scanUDP {
my $address = shift;
my $port = shift;
my $socket = new IO::Socket::INET (
PeerAddr => $address,
PeerPort => $port,
Proto => 'udp',
) or return 0;
$socket -> send('Hello',0);
my $select = new IO::Select();
$select -> add($socket);
my @socket = $select -> can_read(1);
if (@socket == 1) {
$socket -> recv(my $temp, 1, 0) or return 0;
return 1;
}
return 1;
}