如何保持 FTP 连接有效?

问题描述

我使用 ftputil 从 FTP 服务器下载了一批文件。它引发了错误 ftputil.error.FTPIOError: [Errno 60] Operation timed out

Documentation – ftputil中所述,

keep_alive() 尝试保持与远程服务器的连接处于活动状态,以防止发生超时。此方法主要用于在上传或下载文件时保持 FTPHost 对象的底层 FTP 连接处于活动状态。 这将需要在上传或下载过程中使用额外线程,或者从 keep_alive 函数调用 callback

我从 keep_alive 函数调用callback

ftp_host.download(source,target,callback=ftp_host.keep_alive) 

但它引发了 ERROR __main__ keep_alive() takes 1 positional argument but 2 were given

如何保持 FTP 连接有效?

解决方法

这不是直接回答您的问题,但它可能有助于您自己找到特定问题的答案。此外,ftputil 网站上的 ticket 更有助于调试问题。也就是说,我认为最好先询问 StackOverflow,因为您事先不知道问题是否简单。 :-)

由于 FTP 是一种有状态协议,客户端和服务器不能在给定时间发送任意命令。允许的命令和可能的回复由连接所处的状态决定。另请参阅 RFC 959 中的状态图。

为了解决这个限制,ftputil 在幕后为每个远程文件对象创建了一个新的 FTP 连接 [1]。使用这种方法,您仍然可以发送诸如 chdir 之类的命令或在另一个仍在进行中时开始下载。但是,这意味着从服务器的角度来看,所有这些来自单个 FTPHost 对象的 FTP 连接都是独立的连接,因此这些连接中的每一个都可以在不同的时间超时,具体取决于使用模式各自的连接。

例如,有 ftputil ticket 141,推测由 FTPHost 对象发起的主连接超时,而用于下载的连接仍然可用。

在您的情况下,找出哪个底层连接超时(初始连接或远程文件连接)可能会有所帮助。您可以使用 ftputil.session.session_factory 创建启用了 FTP 调试的工厂(请参阅 documentation)。

遗憾的是,60秒的超时时间很短,因此超时的机会相对较多。

特别是考虑到 FTP 连接超时的可能性,我的建议是以某种方式编写用于 FTP 传输的软件,以便您可以在中断的地方重新启动操作(最好使用新的 FTPHost 对象以确保稳健性)通过超时。到目前为止,我还没有想出一种普遍解决超时的方法。在简单的情况下,您可能实际上最好直接使用 ftplib,尽管 ftputil 具有 ftplib 没有的健壮性和延迟改进。使用 ftplib 不会使您免于超时,但至少您没有任何可能使调试更加困难的“隐藏”连接。


[1] 也就是说,如果您在 ftputil 中关闭远程文件,则可以重用底层 FTP 连接,除非它没有超时。库在重用连接之前检查超时。

由于 ftputil 缓存了来自服务器的大量信息以减少延迟,有关超时的情况更加复杂。例如,如果您调用 FTPHost.getcwd(),则从缓存的属性中检索当前目录,而不是通过向服务器发送 PWD 命令从而重置超时。目录列表中的统计信息通常也会被缓存。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...