【问题标题】:Exception class EIdReadTimeout with message 'Read timed out' [Indy-IdFTP]带有消息“读取超时”的异常类 EIdReadTimeout [Indy-IdFTP]
【发布时间】:2015-03-24 22:57:37
【问题描述】:

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

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

文档:

TIdFTP.ReadTimeout - 等待 FTP 协议响应的毫秒数。

TIdFTP.TransferTimeout - FTP 数据通道上读取操作的超时值 客户。

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


我使用 Delphi XE7(我猜它使用 Indy 10)。我的 IdFTP 的 Passive 属性设置为 false。

【问题讨论】:

  • 去掉超时,或者把它变大。无论如何,下载大文件或未知文件大小根本不应该有超时,或者应该设置为大时间。想象一下有人使用非常慢的互联网连接。您使用的是主动模式还是被动模式?哪个版本的 Indy?
  • 如果不复习我的 FTP 知识,我不确定哪个超时,我放弃了使用 FTP,因为它不稳定(用于程序使用)并在很久以前转向 HTTP。但是在某个地方你有一个超时。如果不是,那一定是服务器端的问题。
  • 即使有人可以在没有看到您的完整设置的情况下回答,但根据 Indy 版本和 FTP 模式,答案可能会大不相同。你需要包括那些。但我猜如果你没有超时,那么服务器可能会这样做。你试过不同的服务器吗?
  • 根据您的编辑,您应该查看TransferTimeout。如果那里没有设置超时,那么您需要咨询服务器的供应商。也许 Indy 10 中存在一个错误,很可能 Remy 很快就会在这里阐明这个主题:-)
  • 您在不到 15 分钟的时间内下载了一个 1 GB(1000 兆字节)的文件,而您认为这是一个小文件!?!我记得 1200 波特调制解调器是下载文件的速度之王。

标签: delphi ftp indy indy10


【解决方案1】:

FTP 协议使用多个 TCP/IP 连接 - 一个用于主命令/响应连接,另一个连接用于数据传输。在数据传输过程中,主命令连接处于空闲状态。传输完成后,命令连接会收到响应。

如果您正在通过不支持 FTP 的路由器/防火墙,则如果命令连接在大传输期间闲置时间过长,可能会被终止。连接通常不会“优雅地”终止,因此即使操作系统也不知道连接已经消失。当TIdFTP 尝试读取一个从未到达的传输响应时,它会超时。

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

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

【讨论】:

  • 将它们设置为您想要的任何内容。它们是 Indy 级别的超时,而不是 TCP 级别的超时。不管你希望 Indy 等待单个字节的时间有多长。我通常将它们保留为默认值,或者将它们设置为 10-15+ 秒以解决网络延迟问题。
  • 看看他们的产品规格。
  • 如果它没有明确说明支持 FTP,那么您可能不得不推断它是否真的支持,或者只是联系供应商并询问。
  • 谢谢。你的解决方案奏效了。现在我只需要修复 Connection closed gracefully 错误。