1

バックグラウンド:

Apache Commons.net FTPSClient を使用してファイルを転送するアプリケーションに、ある程度のフォールト トレランスを追加しようとしています。クライアントとサーバー間の接続が失敗した場合、生成された例外/リターン コードをキャプチャし、詳細をログに記録して、再接続/転送の再試行を試みたいと考えています。

機能するもの:

retrieveFile() メソッド。接続が失敗した場合 (つまり、サーバーのパブリック インターフェイスを無効にした場合)、タイムアウトとして指定した時間が経過した後、SocketTimeoutException によって引き起こされた CopyStreamException を受け取ります。

機能しないもの:

storeFile() メソッド。storeFile() を介して転送を開始し、サーバーのパブリック インターフェイスを無効にすると、storeFile() メソッドは、例外をスローすることなく無期限にブロック/ハングします。

接続が終了するとハングする単純なアプリを次に示します。

public class SmallTest {

private static Logger log = Logger.getLogger(SmallTest.class);

/**
 * @param args
 * @throws IOException 
 */
public static void main(String[] args) throws IOException {

    FTPSClient client = new FTPSClient(true);
    FTPSCredentials creds = new FTPSCredentials("host", "usr", "pass", 
            "/keystore/ftpclient.jks", "pass", 
            "/keystore/rootca.jks");

    String file = "/file/jdk-7u21-linux-x64.rpm";
    String destinationFile = "/jdk-7u21-linux-x64.rpm";

    client.setTrustManager(TrustManagerUtils.getValidateServerCertificateTrustManager());
    client.setKeyManager(creds.getKeystoreManager());

    client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
    client.setCopyStreamListener(createListener());

    client.setConnectTimeout(5000);
    client.setDefaultTimeout(5000);

    client.connect(creds.getHost(), 990);   

    client.setSoTimeout(5000);
    client.setDataTimeout(5000);

    if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
        client.disconnect();
        log.error("ERROR: " + creds.getHost() + " refused the connection");
    } else {
        if (client.login(creds.getUser(), creds.getPass())) {
            log.debug("Logged in as " + creds.getUser());

            client.enterLocalPassiveMode();     
            client.setFileTransferMode(FTP.BLOCK_TRANSFER_MODE);
            client.setFileType(FTP.BINARY_FILE_TYPE);

            InputStream inputStream = new FileInputStream(file);

            log.debug("Invoking storeFile()");

            if (!client.storeFile(destinationFile, inputStream)) {
                log.error("ERROR: Failed to store " + file
                        + " on remote host. Last reply code: "
                        + client.getReplyCode());
            } else {
                log.debug("Stored the file...");
            }

            inputStream.close();
            client.logout();
            client.disconnect();
        } else {
            log.error("Could not log into " + creds.getHost());
        }
    }
}

private static CopyStreamListener createListener(){
    return new CopyStreamListener(){
        private long megsTotal = 0;
        @Override
        public void bytesTransferred(CopyStreamEvent event) {
            bytesTransferred(event.getTotalBytesTransferred(), event.getBytesTransferred(), event.getStreamSize());
        }
        @Override
        public void bytesTransferred(long totalBytesTransferred,
                int bytesTransferred, long streamSize) {
            long megs = totalBytesTransferred / 1000000;
            for (long l = megsTotal; l < megs; l++) {
                System.out.print("#");
            }
            megsTotal = megs;
        }
    };
}

接続を実際にタイムアウトにする方法はありますか?

SW バージョン:

Commons.net v3.3 Java 7 CentOS 6.3

前もって感謝します、

  • ジョー
4

1 に答える 1