Search code examples
perldnsnet-ftp

Getting files from Windows host with Perls Net::FTP


The laptops in our company go to the network either about LAN (workplace) or about WLAN (conference room). Depending on how they go to the net, they get from DHCP different IPs.
Certain Perl application on a server, copies files from the client (e.g. laptop above) with Net::FTP. The piece of code looks like this:

# don't wait for ftp-timeout if the host is not reachable
my $alive = Net::Ping::External(host => $clnt_host);
if ($alive) {
    $ftp = Net::FTP->new($clnt_host, Debug => 0, Timeout => 200)
    or return "Cannot connect to $clnt_host: $@\n";
    ....
    ....
}
else {
  dbgout(1, "Host $clnt_host unreachable.\n");
  $st = "'FTPGETFAILED'";
  return ($st);
}

Sometimes the code above doesn't work: Net::Ping::External() returns "alive", but Net::FTP->new() gets a "timeout".

Obviously "FTP" and "ping" resolve the hostname differently.
On the OS ping reslove as follows:

C:\Users\converter>ping -n 1 lap314-034

Ping wird ausgeführt für lap314-034.domain.de [10.140.12.110] mit 32 Bytes Daten:
Antwort von 10.140.12.110: Bytes=32 Zeit=2ms TTL=127

However, "nslookup" returns 2 possibilities:

C:\Users\converter>nslookup lap314-034
Server:  domaincontroller.domain.de
Address:  123.123.123.123

Name:    lap314-034.domain.de
Addresses:  10.192.3.145
          10.140.12.110

The not active IP address is delivered from nslookup at the first place back.
I suppose that Net::FTP also uses this address to connect to the client.

How can I "convince" FTP to use the active DNS entry for the connection?

=============================================================

Thanks for your answers. I followed your suggestions. The solution bases on: http://code.activestate.com/lists/perl-win32-users/32624/

#------------------------------------------------------------------
sub getActiveIP {
#------------------------------------------------------------------
  my $hostname     = shift;

  my $host = (gethostbyname ($hostname))[0] or return undef;
  my @addr = gethostbyname ($host);
  # delete the first 4 array elements
  splice @addr, 0, 4;
  foreach (@addr) {
    my $IPstr = sprintf ("%s", &inet_ntoa ($_));
    my $alive = ping(host => $IPstr);
    if ($alive) {
      return $IPstr;
    }
  }
  return undef;
}

Nevertheless, I believe that a widespread Perl-library should not make such surprises to the user.


Solution

  • How can I "convince" FTP to use the active DNS entry for the connection?

    There is no good way to let Net::FTP decide it. Instead you should determine it outside of Net::FTP and then use the usable IP address instead of the hostname in Net::FTP.

    Maybe you would be able to use only Net::FTP with the new versions (Net::FTP > 3.0) which can use IO::Socket::IP instead of IO::Socket::INET as the underlying module. This module can try all the IP addresses returned for a hostname until it gets a successful connection. But these retries will be done for every connection, that is the control connection and every data transfer. Since the connection to the inactive host only fails after some timeout everything will just be horribly slow.