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.");
    }
}

誰かが助けてくれれば、事前に感謝します。私の実際のコードについてさらに情報が必要な場合は、ここにもっと多くの情報を入れることができます.

4

2 に答える 2

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();このようにして、未定義の動作を行うため、スレッドの終了方法をより適切に制御できます。

于 2012-04-20T11:20:09.227 に答える
0

申し訳ありませんが、すべてのコードを読んでいないことは認めますが、実行中のスレッドを中断したい場合は、次の 2 つのことを行ってください。

  1. 次のように、try/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. 必要に応じて、上記のスレッドの interrupt() メソッドを外部で呼び出します。

例:

thread.interrupt();

これにより、VM が何をしていてもスレッドで InterruptedException をスローするように VM に指示し、いくつかのことを行う機会を与えます。

これがあなたが探しているものであることを願っています...

編集

わかりました、動作する具体的な例:

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);
}

}

于 2012-04-20T09:34:52.153 に答える