2012-04-20 11 views
0

私は現在、接続の速度を見るためのテストを実行するために、commons.netパッケージに基づいてftpクライアントを開発しています。 基本的に私のftpテストは、サーバーに接続してログオンし、必要なだけダウンロード/アップロードのサイクルを開始し、ユーザーがボタンを使って停止することを決定するまで、現在のサイクルは終了しますテスト。進行中のタスクをタイムアウトメカニズムで中断するにはどうすればいいですか?

しかし、これらのテストを実行しているときに、タイムアウトメカニズムを必要とする状況が発生しました。サーバーはファイルを送信していて、実際に完了する前に戻りコード226(転送完了)を送信していました。

私のスレッドは、それがもはや不可能なときにinputStreamを空にしようとしたままです。

私の考えは、ダウンロードプロセスでスレッドタイマーを開始することでした。これは、バイトがクライアントに転送されるたびにリセットされます。 タイムアウトが発生すると、例外が発生し、クライアントがダウンロードに対応して応答します。

私は多くのソリューションを読んでお試しください: - スレッドから例外を発生させる - >スレッドはクライアントではなく例外をキャッチします。 - スレッドからクライアントを中断するので、クライアントはinterruptedExceptionを発生させます - >動作していないようです。 - タイムアウトのエグゼキュータを使用する - >ダウンロードの「通常の」持続時間を知ることができないため、タスクを開始するときにエグゼキュータに与えることはできません。また、タイマーはリセットする必要があります。データを受信する。

私は多くのフォーラムでこれについて多くを読んでおり、この場合は適合して動作するように見える解決策は見つかりませんでした。誰かがそれを行う別の方法のアイデアを持っている場合は?

これは私が行っており、アクションのコードです:

public double get(String fileName) { 
    [...] 
    org.apache.commons.net.io.Util.copyStream(stO,stD,client.getBufferSize(), 
       this.localSize, 
       new org.apache.commons.net.io.CopyStreamAdapter() { 
        public void bytesTransferred(long totalBytesTransferred, 
          int bytesTransferred,long streamSize) { 
         setProgressDL(totalBytesTransferred); 
         //reset the timer here 
        } 
     }); 
[...] 
} 

をここでは私のクライアントを起動し、私のテストのコードの一部です:誰でも可能であれば

public class TestFtp extends Thread { 
[...] 
public void run() { 
    System.out.println("Launching FTP test"); 
    FtpClient client = new FtpClient(this.model, this, this.model.getFtpServer()); 
    try { 
        //Attempting connection on the server 
     client.connect(); 
     try { 
      // Attempting login 
      client.login(this.model.getUsername(), this.model.getPassword()); 
      do { 
       client.changeDirectory("get"); 
            // start timer 
       client.get(this.model.getDistantFileName()); 
            // stop timer 

       client.changeToParentDirectory(); 
       client.changeDirectory("put"); 
       client.set(this.model.getDistantFileName(), 
         this.model.getNewFileName()); 

       client.changeToParentDirectory(); 
       try { 
        // Little pause between each test 
        Thread.sleep(500); 
       } catch (InterruptedException e) {} 
       // Continue test until the user stops it 
      } while (this.continuous); 
      // Once the test is over, logout 
      client.logout(); 

      } catch (FTPLoginException e) { 
      // If login fails, the test ends 
      System.out.println("Unable to login to the server."); 
     } 
    } catch (FTPConnectException e) { 
     // If connection error, the test ends 
     System.out.println("Unable to connect to the server."); 
    } 
} 

は事前によりありがとう私の実際のコードについてさらに詳しい情報が必要な場合は、ここにそれ以上の情報を入れることができます。

+0

InputStream APIを直接使用していないと思われます。そうしないと、in.available()のようなことができますか?そうでない場合は、少し時間をおいてください。データがまだない場合は、接続が失われていると想定してください。 –

+0

Thread.interrupt()はスレッドを中断し、途中にある貪欲コードがそれを食べていない限り、 –

答えて

0

まあ、私は申し訳ありませんが、私は、私はすべてのあなたのコードを読んでいないが、あなたは実行中のスレッドを中断したい場合は、2つのことを行う認める:

  1. は/トライ内のスレッドのコードを実行しますこのようなcatchブロック:

例:

public void run() { 
    try { 
     // code to run 
    } catch (InterruptedException ie) { 
     // thread interrupted, may want to do some clean up 
     // but must return as quickly as possible to avoid halting external code 
    } 
} 
  1. コール上記外部Wスレッドの割り込み()メソッド必要が生じます。

例:

thread.interrupt(); 

これはあなたにいくつかのものを行うための機会を与え、関係なく、それはやっているものをお使いのスレッドで例外:InterruptedExceptionをスローしないようにVMを教えてくれます。

私はこれがあなたが探していることを望みます...[OK]を

EDIT

、作品の具体的な例:

public class Driver { 

private static int count = 0; 

public static void main(String[] args) { 

    Thread t = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       bigTask(); 
      } catch (InterruptedException ie) { 
       System.out.println("Interrupted thread! Count is " + count); 
      } 
     } 
    }); 

    t.start(); 

    try { 
     Thread.sleep(1000); 
     System.out.println("Trying to interrupt thread"); 
     t.interrupt(); 
    } catch (InterruptedException e) {} 

} 

private static void bigTask() throws InterruptedException { 
    List<BigDecimal> bigs = new ArrayList<BigDecimal>(); 
    for (int i = 0; i < 10000000; i++) { 
     bigs.add(BigDecimal.valueOf(i)); 
     if (Thread.interrupted()) { 
      throw new InterruptedException(); 
     } 
     count = i; 
    } 
    System.out.println("Ok, added ten million items, count is " + count); 
} 

}

+0

ああ、忘れて言えば、あなたがsleep()の呼び出しの周りにあるtry/catchブロックを削除していることを忘れてしまった。 – Renato

+0

このような例外をスローすることができるtryとcatchの間にコードをいくつか持たなければならないので、これを行うことはできません。なぜなら、sleepはinterruptExceptionをスローするので、** sleep * – Jzux

+0

@Jzuxこれのためにスリープする必要はありません。スレッドには中断されたフラグをチェックするメソッドがあります。これらを使用して、中断された例外を自分で投げることができます。 –

0

をあなたがに、不要な例外をスローしたくない場合は、あなたがの実行を制御するブール型のフラグを使用する必要がありますスレッド(または実行可能ファイル):

public class TestFtp extends Thread { 
[...] 
boolean abort; 
public void run() { 
    [...] 
    do{ 
     [...] 
    } while (this.continuous && !abort); 
    if (abort){ 
     // You might want to do something here 
    }else{ 
     // The stuff you normally do 
    } 
} 
} 

さらに、abortフラグを外部からfalseにフラグします。 thread.interrupt();には未定義の動作があるため、スレッドの終了方法をより適切に制御できます。

+0

実際、ストリームのコピーを実行しているので、アプリケーションの動作を制御できないため、ブール値の値はテストされません。 – Jzux

+0

その後、@Renatoが提案した解決策を使用しますが、実行される内容を制御することはできません。 –

+0

私はRenatoのソリューションを編集し、 を追加しました。if(false)throw new InterruptedException(); これはコンパイラをだますべきであり、動作する可能性があります –

関連する問題