バックグラウンド:
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
前もって感謝します、
- ジョー