检测Java FTP客户端的丢失连接



我使用commons net中的Java FTPClient类从ftp服务器下载大型文件。如果我检测到一些连接故障,比如:我的客户端连接断开或我的服务器关闭连接,我希望文件从某个偏移量重新开始下载。有了client.retrieveFile(filename, out),如果我在下载文件时关闭客户端连接,我不会遇到任何异常,程序就会冻结在那里,而不会下载或做任何事情。如何触发此事件?我看到一个FTPConnectionClosedException,但只有当服务器关闭我的连接时才会调用它。

您可以保留某种序列id,它可以表示下载了多少数据,并在合法完成后将其设置为某个特殊值。

sequence=0;
try{
while(notDone){
   n = client.retrieveFile(filename, out); //bytes read
   sequence =+ n;
}finally{
if(sequence != SPECIAL_VALUE){
    throw new customException();
    }
}

最终,你的代码将执行finally block,你可以决定如何处理它。或者,如果你想要一个更fail fast的解决方案,你可以通过测量sequence上次更新的时间来使用超时。

希望这能有所帮助!

您可以在下载过程中定期调用parallel therad中的ftpClient.getState()。如果连接断开,它会抛出SocketTimeoutException。此外,之前您需要通过ftp.setControlKeepAliveTimeout(5) 设置超时(例如5秒)

这是样品:

ftpClient.setControlKeepAliveTimeout(5);
Callable<Boolean> downloadTask = () -> {
    try {
        return ftpClient.retrieveFile(name, counterOutput);
    } catch (IOException e) {
        Logger.error(e.getMessage(), e);
        return false;
    }
};
Callable<Boolean> connectionCheckTask = () -> {
    try {
        while(true) {
            Thread.sleep(5000);
            ftpClient.getStatus();
        }
    } catch (SocketTimeoutException e) {
        Logger.error("Connection is broken", e);
        return false;
    } catch (InterruptedException e) {
        Logger.error(ex.getMessage, e);
        return false;
    }
};
ExecutorService execSvc = Executors.newCachedThreadPool();
Boolean result = execSvc.invokeAny(Arrays.asList(downloadTask, connectionCheckTask));
execSvc.shutdown();

我不认为这是一个完美的解决方案,但它对我有效。

最新更新