异常 class EIdReadTimeout 消息 'Read timed out' [Indy-IdFTP]

Exception class EIdReadTimeout with message 'Read timed out' [Indy-IdFTP]

我想从 FTP 下载文件。如果文件很小(通常小于 1000MB),它就可以工作。但是,如果文件很大,我会得到一个 EIdReadTimeout。为什么?我应该保持连接吗?据我所知,读取数据有自己的通道,所以我不必保持连接。

奇怪的是异常出现在Get的最后(Get成功下载整个文件后):FTP.Get(Name, TempGzFile, TRUE, FALSE) !!!!

文档:

TIdFTP.ReadTimeout - Number of milliseconds to wait for an FTP protocol response.

TIdFTP.TransferTimeout - Timeout value for read operations on the data channel for the FTP client.

默认情况下,ReadTimeout 设置为 60 秒,TransferTimeout 设置为 10 秒。


我正在使用 Delphi XE7(我猜它使用的是 Indy 10)。我的 IdFTP 的被动 属性 设置为 false。

FTP 协议使用多个 TCP/IP 连接 - 一个用于主 command/response 连接,另一个连接用于数据传输。当数据传输正在进行时,主命令连接处于空闲状态。传输完成后,命令连接会收到响应。

如果您正在通过一个 router/firewall 并没有 FTP-aware,如果命令连接在大型传输过程中闲置太久,它可能会被终止。连接通常不会被杀死 "gracefully",所以即使 OS 也不知道连接已经消失。当 TIdFTP 然后尝试读取从未到达的传输响应时,超时。

为了解决这个问题,请使用 TIdFTP.NATKeepAlive 属性 在传输期间在命令连接上启用 TCP/IP 级别保持活动状态。将NATKeepAlive.UseKeepAlive设置为True,将NATKeepAlive.IdleTimeMS(keepalive开始发送前的空闲超时时间)和NATKeepAlive.IntervalMS(每次keepalive之间的间隔时间)设置为合适的值。

但是请注意,目前 IdleTimeMSIntervalMS 仅针对 Windows 2000+、Linux 和 BSD 实现。其他平台使用 OS 提供的默认值(往往非常大)。如果您需要自定义这些平台上的值,您可以根据需要使用 TIdFTP.OnDataChannelCreateTIdFTP.OnDataChannelDestroy 事件直接调用 TIdFTP.Socket.Binding.SetSocketOption()