Python:ftplib在传输结束时挂起

Python:ftplib在传输结束时挂起,第1张

Python:ftplib在传输结束时挂起

没有更多信息,我实际上无法调试您的问题,因此我只能提出最一般的答案。这可能对您来说不是必需的,但对任何人来说都足够了。

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正常加速到全速运行。但它应该工作。

请查看此答案-并注意,它需要针对特定​​的故障服务器进行一些测试,以找出哪些变体可以正确,有效地工作。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5631904.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存