检查是否在Perl中打开了UDP端口

时间:2014-04-06 12:55:10

标签: perl udp

我需要检查是否打开了远程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”以检查端口是否已打开。但是我怎么能这样做呢?

3 个答案:

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