Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

i have written a perl subroutinue which uploads a file from my local machine(Linux) to an ftp server.This script uses Net::FTP module.The script is able to open a connection,login into the ftp server,but while executing put function giving an error like "can't open data connection" through ftp->message function..any idea why it is happenning..please help me thanx kamesh

Replies are listed 'Best First'.
Re: problem with put function
by BrowserUk (Pope) on Oct 12, 2004 at 10:47 UTC
    any idea why it is happenning

    It's probably that comma on line 21.

    And if there is no comma on line 21, perhaps you could post your code as my ESP seems to be acting up this week :)


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
      <body>when i execute the script with debug option set following is the output
      Net::FTP: Net::FTP(2.65)
      Net::FTP: Exporter(5.567)
      Net::FTP: Net::Cmd(2.21)
      Net::FTP: IO::Socket::INET(1.26)
      Net::FTP: IO::Socket(1.27)
      Net::FTP: IO::Handle(1.21)
      Net::FTP=GLOB(0x82b0570)<<< 220 ftp FTP server (Version wu-2.6.2-5) ready.
      Net::FTP=GLOB(0x82b0570)>>> user *****
      Net::FTP=GLOB(0x82b0570)<<< 331 Password required for *****.
      Net::FTP=GLOB(0x82b0570)>>> PASS ....
      Net::FTP=GLOB(0x82b0570)<<< 230 User ***** logged in. Access restrictions apply.
      Net::FTP=GLOB(0x82b0570)>>> CWD /
      Net::FTP=GLOB(0x82b0570)<<< 250 CWD command successful.
      Net::FTP=GLOB(0x82b0570)>>> TYPE A
      Net::FTP=GLOB(0x82b0570)<<< 200 Type set to A.
      Net::FTP=GLOB(0x82b0570)>>> PASV
      Net::FTP=GLOB(0x82b0570)<<< 227 Entering Passive Mode (***,***,***,**,***,***)
      Net::FTP=GLOB(0x82b0570)>>> STOR oldkamsApplicationLog.txt
      Net::FTP=GLOB(0x82b0570)<<< 425 Can't open data connection
      thanx
      kamesh
      </body>
        my code is here
        sub FtpToDCLKServer(\%$\$\$) {
        my $V_ConfigHashRef = shift;
        my $V_LocalFile = shift;
        my $V_RemoteFileNameRef = shift;
        my $V_RemoteFileSizeRef = shift;
        my $V_CurrentDate = GetTheCurrentDate(); #get today's date
        my $V_HostName = $V_ConfigHashRef->{FTPHostName}; #get ftp hostname from the hash
        my $V_UserName = $V_ConfigHashRef->{FTPUserName}; #get ftp user name from the hash
        my $V_Password = $V_ConfigHashRef->{FTPPassword}; #get ftp password from the hash
        my $V_Directory = $V_ConfigHashRef->{FTPDir}; #get the ftp directory on to which we have to place the files
        my $V_Ftp;
        if ( $V_Ftp = Net::FTP->new($V_HostName) ) { #instantiate new ftp object
        unless ($V_Ftp->login($V_UserName,$V_Password)) { #login to the ftp server
        WriteToLogFile($V_CurrentDate,GetTheCurrentTime(),"Error","Could not login:$@");
        return 0;
        }
        $V_Ftp->pasv(); #continue the session in passive mode
        unless ($V_Ftp->cwd($V_Directory)) { #change the current working directory to $V_Directory
        WriteToLogFile($V_CurrentDate,GetTheCurrentTime(),"Error","Could not change the current working directory to $V_Directory");
        return 0;
        }
        unless($V_Ftp->ascii) { #transfer the data in ascii mode
        WriteToLogFile($V_CurrentDate,GetTheCurrentTime(),"Error","Could not change to ASCII mode");
        return 0;
        }
        unless ($$V_RemoteFileNameRef = $V_Ftp->put($V_LocalFile,"Curve_"."$V_CurrentDate"."\.dat")) { #upload the file
        WriteToLogFile($V_CurrentDate,GetTheCurrentTime(),"Error","$V_Ftp->message");
        return 0;
        }
        $$V_RemoteFileSizeRef = $V_Ftp->size($$V_RemoteFileNameRef);
        $V_Ftp->close(); #close the ftp session
        }else {
        WriteToLogFile($V_CurrentDate,GetTheCurrentTime(),"Error","Could not connect:$@");
        return 0;
        }
        return 1;
        }
        thanx
        kamesh
Re: problem with put function
by ikegami (Pope) on Oct 12, 2004 at 15:27 UTC
    Passive (PASV) connections tend not to work when the FTP server is behind a firewall/NAT/router. Did you try an active (PORT) connection?
      can you elaborate this thing?
      thanx
      kamesh

        Sure thing.

        Say SERVER is 1.2.3.4.
        Say SERVER runs an FTP server on port 21.
        Say CLIENT is 5.6.7.8.

        In active (PORT) mode, the dialog for a file transfer looks something like this:

        +--------+ +--------+ | CLIENT | | SERVER | | |Makes connection to 1.2.3.4, port 21. | | | |>------------------------------------------>| | | |This is the control connection. | | | | | | | | | | | |Starts listening on a random port.[*] | | | | | | | | | | | |Sends "PORT 5,6,7,8,45,35" | | | |>------------------------------------------>| | | |over the control connection. | | | | | | | | | | | | Makes connection to 5.6.7.8, port 11555.| | | |<==========================================<| | | | This is the data connection.| | | | | | | | | | | |Sends retrieve command ("RETR filename") | | | |>------------------------------------------>| | | |over the control connection. | | | | | | | | | | | | Sends file "filename"| | | |<==========================================<| | | | over the data connection.| | | | | | +--------+ +--------+
        [*]
        The arguments to PORT are the bytes of the IP address (in decimal) and the bytes of the port to which the server should connect in (decimal), each byte seperated by a comma. The port is randomly assigned to allow multiple connections between the two machines. I used port 11555 in the example, where 11555 = 0x2D23, 0x2D = 45, and 0x23 = 35.

        Firewalls which are not specifically aware of FTP don't know that the incoming (data) connection shouldn't be blocked, and NAT routers which not are not specifically aware of FTP don't know to which machine to forward the incoming (data) connection.

        In passive (PASV) mode, the dialog for a file transfer looks something like this:

        +--------+ +--------+ | CLIENT | | SERVER | | |Makes connection to 1.2.3.4, port 21. | | | |>------------------------------------------>| | | |This is the control connection. | | | | | | | | | | | |Sends "PASV" | | | |>------------------------------------------>| | | |over the control connection. | | | | | | | | | | | | Starts listening on a random port.[*]| | | | | | | | | | | | Sends a response with the port num 11555| | | |<------------------------------------------<| | | | over the control connection.| | | | | | | | | | | | Makes connection to 1.2.3.4, port 11555.| | | |>==========================================>| | | | This is the data connection.| | | | | | | | | | | |Sends retrieve command ("RETR filename") | | | |>------------------------------------------>| | | |over the control connection. | | | | | | | | | | | | Sends file "filename"| | | |<==========================================<| | | | over the data connection.| | | | | | +--------+ +--------+

        In this scenerio, the client doesn't need to accept any incoming connection. Many FTP clients now default to passive mode due to the popularity of NAT for home machines.

        Notes

        FTP's multiple connections has been very troublesome to people configuring firewalls and requires firewalls to be aware of FTP specifically (while they don't need to know about anything HTTP, for example). If you have trouble getting a directory listing from a FTP server after supplying your user name and your password, it's probably because of firewall/NAT issues, since directory listings treated like a file transfer. Try switching between active and passive mode.