http://www.perlmonks.org?node_id=146652


in reply to "canned" FTP

I second Ovid's suggestion of using Net::FTP. It's a much more elegant solution.

But in any case, I can't say I know everything there is to know about the mechanics of FTP, but it's my understanding that while port 21 is the port used for making ftp connections, port 20 is the "ftp-data" port, unless you're using PASV mode, which is usually the case when FTPing from behind a firewall, etc. Anyhow, I think PASV mode allows the data to travel all on one port, rather than two. How you might go about using sockets to receive the data on ftp-data port 20, I'm not really sure.

Replies are listed 'Best First'.
Re: (Kozz) Re: "canned" FTP
by rob_au (Abbot) on Feb 21, 2002 at 01:15 UTC
    I think you are spot-on with this suggestion Kozz - The problem here seems to relate more to the specifics of the FTP connection and network translation than the program code itself. I have discussed this aspect of FTP transfer previously in some detail in the node Re: Net::FTP Unexpected EOF.

    While the node referenced above deals more specifically with the usage of Net::FTP (which I believe would offer a much cleaner and compact solution in this case), PASV behaviour as discussed in the above node can be initiated within a FTP session through the issuing of the command PASV prior to any commands which make use of the ftp-data connection (eg. LIST).

    Using the code in question as a base ...

    print FTP "PASS password\r\n"; sysread (FTP, $FormData, 1024); print STDOUT "$FormData\n"; print FTP "PASV\r\n"; sysread (FTP, $FormData, 1024);

    Just on a final note, you know that by introducing sysread in the manner that you have, you have also introduced some very nasty buffer dependencies in your code - This in itself could cause a number of headaches as your code is moved into production.

     

    perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s& .com.&_&&&print'

      ok, i have tried a different approach using the PASV approach, but i still get "425 can't build data connection" in the following example... obviously i'm lost...lol...
      print FTP "PASV\r\n"; sysread (FTP, $FormData, 1024); print STDOUT "$FormData\n"; print FTP "LIST\r\n"; sysread (FTP, $FormData, 1024); print STDOUT "$FormData\n"; socket (DATA, AF_INET, SOCK_STREAM, getprotobyname('tcp')); bind (DATA, pack('S n a4 x8', AF_INET, 20, (gethostbyname($FTPdServer) +) [4])); listen (DATA, 1); while (<DATA>) { $FormData = $_; print STDOUT $FormData; } close (DATA); print FTP "QUIT\r\n"; sysread (FTP, $FormData, 1024); print STDOUT "$FormData\n"; close (FTP);
        What happenned to   accept (DATA,IOS)  ?

          p
Re: (Kozz) Re: "canned" FTP
by PriNet (Monk) on Feb 21, 2002 at 00:21 UTC
    i'm an assembly programmer by heart, so i would rather try to do "this" written from raw code as compared to using the Net::FTP module. i'm new to using sockets so bear with me, i just prefer understanding (by snippets/examples) how to accomplish this in the absolute basic bottom line. perhaps someone can direct me to the code listing for Net::FTP rather than just the most common "how to use" reference? i have no queries that if i could get a visual of the module, i could understand how its done... thanx for everyones response, i have been looking at the Net::FTP option, but, it doesnt do the proverbal "inside workings" that i yern for....lol

      perhaps someone can direct me to the code listing for Net::FTP

      Well first you install Net::FTP then examine the FTP.pm file that is in the distribution directory (possibly in lib/Net/FTP.pm - I don't have an unpacked one to hand :) - you will find that you will also need to refer to the code Net::Cmd. of which Net::FTP is a subclass. You will see firstly that the Net::* modules all use the module IO::Socket rather than going straight to the naked socket routines - this gives them a clearer and easier to understand implementation IMO.

      /J\

Re: FTP connections
by jeffenstein (Hermit) on Feb 21, 2002 at 15:04 UTC

    Passive mode ftp still uses a second connection for data, just the direction of the connection differs.

    In normal 'active' ftp, the client connect to remote port 21 for control, and data connections come back from the server with a source port of 20 and destination port > 1024. In 'passive' ftp, the client still connect to remote port 21 for control, however data connections originate _from_ the client on a port > 1024 to the remote server on a port > 1024, thus passing through firewalls that only allow outgoing connections.

    Then, of course, is the issue of binary mode encoding, translating between formats, etc... Much easier to use Net::FTP, unless you have a week or so to kill on a 15 minute job. ;-)