You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@commons.apache.org by Ghislain Gadbois <gh...@bell.ca> on 2006/04/05 19:16:24 UTC

RE: [Net]: FTPClient.abort problem

Hi all,

Sorry for not posting back sooner... I've been kinda busy lately...

I finally figured out how to solve the FTP abort problem I had, thanks to Daniel Savarese and to Martin Brunninger for their input...  They guided my on the right way!

First, I wrapped all my FTP code in a class.  Every Java class that wants to do FTP uses my class...

In my class, I use a monitor to synchronize thread access.  So every call to the FTPClient methods are wrapped in a synchronized(monitor) block.

Next, in my put and in my get methods, I use retrieveFileStream and storeFileStream and I pass the stream to a method which is responsible for transferring data between hosts.  I also store the thread that is doing the transfer so I can interrupt it later in my abort method.

In this transfer method, I check the Thread.currentThread().interrupted() flag to see if the transfer thread has been interrupted.  If it is interrupted, I call wait() on my monitor so I can abort the transfer properly.  This actually aborts the transfer on the client side.

Then, in my abort method, I first interrupt the transfer thread (to abort the transfer on the client side...), then, in my synchronized(monitor) block, I call the FTPClient.abort() mehtod.  This will actually abort the transfer from the server side.

Then, since both the client and the server are interrupted, I need to synchronize the response codes.  Remember from my original post that I got the 426 for the file transfer first, and then the 226 response indicating that the abort command was successful.  Normally, the FTPClient class usually takes the 426 for the abort, and the 226 for the transfer...

To trick the FTPClient class to process the return codes in the right order, I use a ProtocolCommandListener.  In the protocolCommandSent method, I first do a sleep(100) to give a chance to the server to process the abort command.  Then, I call monitor.notifyAll().  This will actually wake up the transfer thread that I put in wait mode when I started the abort process...  Then, I call monitor.wait(100) in the current thread to give the transfer thread a chance to process it's 426 code.  Remember that the transfer code is in a synchronized(monitor) block, so if I don't wait, the abort thread will get the 426...

Finally, in the transfer thread, I just handle the transfer as usual by calling completePendingCommand()...

In the abort thread, since I called wait(100), the abort thread will wake up 100 miliseconds later and it will process the 226 response code.

So, it's kind of a tricky way to handle the aborts, but it works fine!

I hope this helps someone, and, once again, thanks to Daniel and Martin who helped me solve this!

Cheers!!!

Ghis


 



-----Message d'origine-----
De : Ghislain Gadbois [mailto:ghislain.gadbois@bell.ca]
Envoyé : 13 mars 2006 14:29
À : commons-user@jakarta.apache.org
Objet : [Net]: FTPClient.abort problem


Hi,

I'm using Jakarta Commons Net's FTPClient to do FTP transfers.  I use version 1.4.1 on J2SDK 1.4.2_11.

I'm trying to abort an FTP transfer in a separate thread.

What happens is:
1- The thread that is downloading the file is not interrupted so the file is all downloaded
2- Since the download thread is not interrupted, the responses are not handled properly:
   * The thread that is calling abort() gets a 426 - transfer aborted response
   * The thread that is downloading the file get 226 ABOR command succesful

Following this message is a sample program to reproduce the problem and a sample of this program's output...

Is there something that I'm doing wrong?

What would be required to solve the problem?

Thanks a lot for your help!


Ghis


---------- Sample code -------------

import java.io.FileOutputStream;
import org.apache.commons.net.ProtocolCommandEvent;
import org.apache.commons.net.ProtocolCommandListener;
import org.apache.commons.net.ftp.FTPClient;

public class TestsNetCommons
{
    public static void main(String[] pasArgs)
    {
        final Object            oMonitor    = new Object();
        FTPClient               oFtp        = null;
        Thread                  oThread;
        ProtocolCommandListener oListener   = new ProtocolCommandListener()
        {
            public void protocolCommandSent(ProtocolCommandEvent poEvent)
            {
                String sMessage;

                sMessage = poEvent.getMessage();

                if(sMessage != null)
                {
                    sMessage = sMessage.trim();
                }

                // Remove the password from the log files...
                if(sMessage.startsWith("PASS "))
                {
                    sMessage = sMessage.substring(0, 5) + "*****";
                }

                System.out.println("Client:  " + sMessage);
            }


            public void protocolReplyReceived(ProtocolCommandEvent poEvent)
            {
                String sMessage;

                sMessage = poEvent.getMessage();

                if(sMessage != null)
                {
                    sMessage = sMessage.trim();
                }

                System.out.println("Server:  " + sMessage);
            }
        };

        try
        {
            oFtp = new FTPClient();

            oFtp.addProtocolCommandListener(oListener);

            oFtp.connect("127.0.0.1");

            if(oFtp.login("ftptest", "ftptest"))
            {
                final FTPClient oFtpClient = oFtp;

                // Thread used to download a file...
                oThread = new Thread()
                {
                    public void run()
                    {
                        FileOutputStream oOut = null;

                        try
                        {
                            oOut = new FileOutputStream("C:\\bigfile.zip");

                            oFtpClient.retrieveFile("bigfile.zip", oOut);
                        }
                        catch(Exception ex)
                        {
                            ex.printStackTrace();
                        }
                        finally
                        {
                            if(oOut != null)
                            {
                                try
                                {
                                    oOut.close();
                                }
                                catch(Exception ex)
                                {
                                    // Don't care...
                                }
                            }
                        }
                    } // run                };

                oThread.start();

                // Wait a little, then abort the transfer...
                Thread.currentThread().sleep(1000);
                oFtp.abort();

                // Wait for the download thread to finish it's job
                oThread.join();
            }
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
        finally
        {
            if(oFtp != null)
            {
                try
                {
                    oFtp.logout();
                    oFtp.disconnect();
                }
                catch(Exception ex)
                {
                    ex.printStackTrace();
                }
            }
        }
    }
}


------------- Sample output --------------------

Server:  220 localhost Microsoft FTP Service (Version 5.0).
Client:  USER ftptest
Server:  331 Password required for ftptest.
Client:  PASS *****
Server:  230 User ftptest logged in.
Client:  PORT 127,0,0,1,10,174
Server:  200 PORT command successful.
Client:  RETR bigfile.zip
Server:  150 Opening ASCII mode data connection for bigfile.zip(29716750 bytes).
Client:  ABOR
Server:  426 Connection closed; transfer aborted.
Server:  226 ABOR command successful.
Client:  QUIT
Server:  221


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org