当将ftpClient.connect
与没有 ftp 服务活动的现有主机一起使用时,超时仅在 5 分钟后发生,这太长了。
我尝试设置不同的超时(setDefaultTimeout,setDataTimeout),但没有改变任何东西。
FtpClient
继承自具有setConnectTimeout方法SocketClient
,但是当我使用它时,我在运行它时会得到java.lang.NoSuchMethodError: org/apache/commons/net/ftp/FTPClient.setConnectTimeout
。这似乎是因为一些J2SW 1.2兼容性,如Commons-net FAQ中所述:
问:如何设置连接超时? http://wiki.apache.org/commons/Net/FrequentlyAskedQuestions
他们建议实现自己的SocketFactory
,使用特定的超时从扩展的 Socket 类创建对象。但是,当尝试使用ftpClient.setSocketFactory
时,我也得到了一个java.lang.NoSuchMethodError
.
任何帮助如何减少连接超时?
FTPClient ftp = new FTPClient();
ftp.setDefaultTimeout();
ftp.setDataTimeout();
ftp.setConnectTimeout();
ftp.setSoTimeout();
ftp.setControlKeepAliveTimeout();
ftp.setControlKeepAliveReplyTimeout();
来自 Apache 文档:
/**
* Set the default timeout in milliseconds to use when opening a socket.
* This value is only used previous to a call to
* {@link #connect connect()}
* and should not be confused with {@link #setSoTimeout setSoTimeout()}
* which operates on an the currently opened socket. _timeout_ contains
* the new timeout value.
* <p>
* @param timeout The timeout in milliseconds to use for the socket
* connection.
*/
void setDefaultTimeout(int timeout);
/**
* Sets the timeout in milliseconds to use when reading from the
* data connection. This timeout will be set immediately after
* opening the data connection, provided that the value is ≥ 0.
* <p>
* <b>Note:</b> the timeout will also be applied when calling accept()
* whilst establishing an active local data connection.
* @param timeout The default timeout in milliseconds that is used when
* opening a data connection socket. The value 0 means an infinite timeout.
*/
void setDataTimeout(int timeout)
/**
* Sets the connection timeout in milliseconds, which will be passed to the {@link java.net.Socket} object's
* connect() method.
* @param connectTimeout The connection timeout to use (in ms)
* @since 2.0
*/
void setConnectTimeout(int connectTimeout);
/**
* Set the timeout in milliseconds of a currently open connection.
* Only call this method after a connection has been opened
* by {@link #connect connect()}.
* <p>
* To set the initial timeout, use {@link #setDefaultTimeout(int)} instead.
*
* @param timeout The timeout in milliseconds to use for the currently
* open socket connection.
* @exception SocketException If the operation fails.
* @throws NullPointerException if the socket is not currently open
*/
void setSoTimeout(int timeout) throws SocketException;
/**
* Set the time to wait between sending control connection keepalive messages
* when processing file upload or download.
*
* @param controlIdle the wait (in secs) between keepalive messages. Zero (or less) disables.
* @since 3.0
* @see #setControlKeepAliveReplyTimeout(int)
*/
void setControlKeepAliveTimeout(long controlIdle);
/**
* Set how long to wait for control keep-alive message replies.
*
* @param timeout number of milliseconds to wait (defaults to 1000)
* @since 3.0
* @see #setControlKeepAliveTimeout(long)
*/
void setControlKeepAliveReplyTimeout(int timeout)
它一定是你调用setConnectTimeout的方式,因为它确实存在。 setConnectTimeout 不是静态调用,您必须在分配 FTPClient 对象后调用它,并在连接之前执行设置。
FTPClient ftp = new FTPClient();
ftp.setConnectTimeout(5000); // 5000 Milliseconds (5 Seconds)
...
ftp.connect(server, port);
虽然旧版本的共享资源网络库有可能的解决方案,但我建议弄清楚为什么使用错误版本的共享资源网络。为此,您可以在 Web 应用中使用 FTPClient
的位置包含以下代码:
FTPClient ftpClient = ...;
if(ftpClient.getClass().getClassLoader() instanceof java.net.URLClassLoader) {
URL[] urls = ((java.net.URLClassLoader) ftpClient.getClass().getClassLoader()).getURLs();
// log these urls somewhere and check - these are urls from where your FTPClient may be loaded from
}
如果FTPClient
不是由java.net.URLClassLoader
加载的,那么检查类路径可能会变得更加复杂,尽管这应该不是问题。
希望这有帮助...
只是为了对这些值添加一些说明(在手动测试了很多组合之后,并且只是提到这与使用 under apache FTPClient
的 Spring DefaultFtpSessionFactory
有关 - 所以最终适用于那个):
import org.springframework.integration.ftp.session.DefaultFtpSessionFactory;
DefaultFtpSessionFactory factory = new DefaultFtpSessionFactory();
/**
* Controls 2 values:
* 1. protected abstract void connect(SocketAddress address, int timeout) throws IOException;
* --> controls timeout when opening socket connection. this one is by default 0 in java-code,
* but since OS is controlling this it has some default value - for me in win.
* it was ~20 seconds. If set to lower value it will be respected. If set >20 in my case,
* it always treats it as if 20 was set
* 2. _socket_.setSoTimeout(connectTimeout);
* --> controls timeout after socket is open (so if FTP server is not responding after
* socket is successfully connected). Default is unlimited so good to set to some sane value
* otherwise if no response from FTP Server, connection will hang. Overwrites setDefaultTimeout
* if already set - but only for this connection time (not after FTP server responds first time
* with some data).
*/
factory.setConnectTimeout((int) Duration.ofMinutes(1).toMillis());
/**
* Controls timeout after socket is open (so if FTP server is not responding after socket is
* successfully connected).(IF NOT ALREADY SET IN setConnectTimeout),
* but also controls timeout when reading data from socket after the connection has been made.
* So if FTP client sends "LIST /" command, and there is no answer from FTP server, without
* setting this it will hang (since default is 0). Set to some sane value
* (since server can actually be busy with creating listing of folders for longer time etc.).
*/
factory.setDefaultTimeout((int) Duration.ofMinutes(1).toMillis());
/**
* Controls how long to wait if there is a socket inactivity during FILE-related operations.
* E.g. if we start to download some file from FTP server, this timeout is respected.
* This is by default set to 0 (that is infinite wait). If set to 10 seconds, and there is at
* least some activity in communication (eg. every 9 seconds something is received) then there
* will be no timeout. Only if there is some delay/inactivity for longer than 10 seconds then
* there will be socketRead0 timeout exception. Should be set, since this is not affected by
* setConnectTimeout or setDefaultTimeout.
*/
factory.setDataTimeout((int) Duration.ofMinutes(1).toMillis());