Tuesday, May 22, 2007

FTPClient timeout values

In looking at the docs for org.apache.commons.net.ftp.FTPClient there are three timeouts which can be configured:

setDefaultTimeout : Set the default timeout in milliseconds to use when opening a socket. This value is only used previous to a call to connect() and should not be confused with setSoTimeout() which operates on an the currently opened socket.

setSoTimeout : Set the timeout in milliseconds of a currently open connection. Only call this method after a connection has been opened by connect().

setDataTimeout : Sets the timeout in milliseconds to use when reading from the data connection. This timeout will be set immediately after opening the data connection.

This seemed confusing so I went ahead and peeked at the source code for FTPClient and the whole thing made sense. So basically the FTPClient uses the underlying java.net.Socket and the various timeouts apply at the various stages of socket usage.

if the setDefaultTimeout is set then the underlying java.net.Socket.setSoTimeout() is set and is used default for all connections made using this FTPClient instance. It basically saves you the trouble of calling setSoTimeout after every connection establishment.

if setSoTimeout is set then the underlying java.net.Socket.setSoTimeout() is set for the current connection and at disconnect() the value reverts back to the defaultTimeout set using the setDefaultTimeout. If you call it before connecting, you'll get a NullPointerException

if setDataTimeout is set then the underlying java.net.Socket.setSoTimeout() is set before a read is performed and after the read completion the timeout value is restored to the pre-read state so basically should be called before a data connection is established (e.g., a file transfer) because it doesn't affect an active data connection. Usually when a read() method tries to read data from a socket the program will block until the data arrives. However, if you set the timeout property, the read() will only wait the specified number of milliseconds. Then, if no data was received, it will throw an InterruptedIOException. The data timeout specified blocks for each socket read() call and is not cumulative of all read calls.

It seems obvious that defaultTimeout will suffice the purpose however there might be need have read specific dataTimeouts (e.g., you don't want a 2 gb file transfer to die just because there is a 10 minute loss of connectivity)...

On another note what value is optimal to set for timeout given its implications at various stages? Online research recommends: timeout for connect : 5 secs, write/reads : 120 secs

Update: 08/23/2007
So the interesting fact is after all the babbling above I was not able to make the above timeouts to work So here's what I tried: I have a file of size 57mb and I tried setting various combinations of timeouts for upload:

- set defaultTimeout (120 secs) and dataTimeout (1200 secs) before establishing login connection --> Result: upload failed with timeout

- set defaultTimeout (120 secs) before login connection and dataTimeout (1200 secs) after login connection (1200 secs) - Result: upload failed with timeout

- set defaultTimeout (120 secs) before login connection and after login connection (1200 secs) connection --> Result: upload failed with timeout

- set defaultTimeout (1200 secs) before login connection --> Result: upload succeeded

So I tried the above @ various times to make sure I am not dealing with a nework spike or any of that sort and got the same results. I will update once I find more on this stuff.

1 comment:

  1. Good job clearing up some of this! The javadocs sure are cryptic around these parts.

    Sadly, doesn't seem to have any effect on the time outs I'm getting uploading files to FTP - only on receiving.

    ReplyDelete