没有更多信息,我实际上无法调试您的问题,因此我只能提出最一般的答案。这可能对您来说不是必需的,但对任何人来说都足够了。
retrbinary将阻塞直到整个文件完成。如果超过5分钟,则整个5分钟内都不会在控制通道上发送任何消息。您的客户端正在超时控制通道,或者服务器正在超时。因此,当您尝试与挂断时
ftp.quit(),它将永远挂起或引发异常。
您可以使用构造
timeout函数上的参数来控制一方的超时
FTP。某些服务器支持
IDLE命令,以允许您设置服务器端超时。但是,即使事实证明适当的超时也是可行的,您如何首先选择适当的超时时间呢?
您真正想做的是防止数据套接字上发生传输时控制套接字超时。但是如何?例如,如果您
ftp.voidcmd('NOOP')经常在回调函数中使用它,就足以保持连接正常运行……但是这也将迫使您阻塞直到服务器响应
NOOP,许多服务器在数据传输之前不会这样做已经完成,这意味着您将永远永久阻塞(或直到另一个超时),而不会获取数据。
处理两个套接字而一个不阻塞另一个套接字的标准技术是类似
select.select或的多路复用器。您可以在此处执行此 *** 作,但是您将不得不放弃使用简单的
retrbinary接口,而是使用
transfercmd显式获取数据套接字。
例如:
def downloadFile(…): ftp = FTP(…) sock = ftp.transfercmd('RETR ' + filename) def background(): f = open(…) while True: block = sock.recv(1024*1024) if not block: break f.write(block) sock.close() t = threading.Thread(target=background) t.start() while t.is_alive(): t.join(60) ftp.voidcmd('NOOP')
另一种解决方案是一次读取20MB,然后调用
ftp.abort(),并使用
rest参数恢复每个新
retrbinary文件的传输,直到到达文件末尾。但是,这样
ABOR可能会永远挂起
NOOP,因此并不能保证任何事情,更不用说服务器不必对此做出响应了。
您 可以
做的就是关闭整个连接(不是
quit,而是
close)。这对服务器来说不是很好,并且可能导致重新发送一些浪费的数据,并且如果过快地杀死套接字,还可能阻止TCP正常加速到全速运行。但它应该工作。
请查看此答案-并注意,它需要针对特定的故障服务器进行一些测试,以找出哪些变体可以正确,有效地工作。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)