ftplib python:NOOP命令在ASCII中不是Binary [英] ftplib python: NOOP command works in ASCII not Binary

查看:836
本文介绍了ftplib python:NOOP命令在ASCII中不是Binary的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个线程化的FTP脚本。当数据套接字正在接收数据时,线程循环会向控制套接字发送NOOP命令,以便在大量传输过程中保持控制连接的存在。



我无法使用 FTP.retrbinary()命令,因为如果我想保持控制连接处于活动状态,我必须将 retrbinary 的数据和控制套接字c>不行。



以下代码:

  def downloadFile(文件名,文件夹): 
myhost ='HOST'
myuser ='USER'
passw ='PASS'
#login
ftp = FTP(myhost,myuser,passw)

ftp.set_debuglevel(2)
ftp.voidcmd('TYPE I')
sock = ftp.transfercmd('RETR'+ filename)
def background():
f = open(文件夹+文件名,'wb')
而真:
block = sock.recv(1024 * 1024)
如果没有阻止:
break
f.write(block)
sock.close()
t = threading.Thread(target = background)
t.start()
while t.is_alive():
t.join(120)
ftp.voidcmd('NOOP')
ftp.quit();



我的问题 FTP.transfercmd(RETR+ filename)默认为ASCII传输,Im传输视频,所以它必须是Binary(因此 ftp.voidcmd('TYPE I ) call to force Binary mode)。



如果我 不要 调用 ftp.voidcmd('TYPE I) NOOP命令发送成功,输出如下:

  * cmd *'NOOP'
* put *'NOOP \r\\\
'
* get *'200 NOOP:正在进行数据传输\''
* resp *'200 NOOP:正在进行数据传输'
* cmd *'NOOP'
* put *'NOOP \r\\\
'
* get *'200 NOOP:正在进行数据传输\'
* resp *'200 NOOP:数据传输正在进行'
* cmd *'NOOP'
* put *'NOOP \r\\\
'
* get *'200 NOOP:正在进行数据传输\''
* resp *'200 NOOP:正在传输数据'

等。但该文件是ASCII码,因此损坏。如果我 DO 调用 ftp.voidcmd('TYPE I),NOOP命令只发送一次,控制套接字不会响应,直到传输完成。如果文件很大,控制套接字会超时,就好像NOOPs从未发送过一样......



非常奇怪,但我相信它很简单。看起来好像 transfercmd()不是按照它应该分裂控制和数据套接字的方式......因此,ftp var不会与数据流分离。 .. 或者其他的东西。奇怪。



预先感谢您提供的任何建议。 tcpdump 确认服务器仅在服务器发送完整文件后发送 226传输完成。



我怀疑这是FTP规范的一部分。



事实上,看看 retrbinary ftplib.py

  self.voidcmd(' TYPE 1')
conn = self.transfercmd(cmd,rest)
while 1:
data = conn.recv(blocksize)
如果不是数据:
break
回调(数据)
conn.close()
返回self.voidresp()

最后一行预计只有在传输完成后才能获得传输结果(如服务器所知)。



实际上,您的代码似乎已丢失 voidresp() bit。



我不是很熟悉ftp,类似于 lftp 的打包程序实际上会为每个并行下载打开新的控制连接。



如果您的文件是真的很大。

FTP有很多扩展,可能有些是您想要的。



或者你可以像这样做一个循环:

  pos = 0 
而不是完整文件:
命令REST
在单独线程中下载一段时间
命令ABRT
等待单独线程中止
pos + =下载块的长度


I have a threaded FTP script. While the data socket is receiving the data, a threaded loop sends NOOP commands to the control socket to keep control connection alive during large transfers.

I am prevented from using the FTP.retrbinary() command as, if I want to keep the control connection alive I must separate the data and control sockets which retrbinary does not do.

Code below:

def downloadFile(filename, folder):
    myhost = 'HOST'
    myuser = 'USER'
    passw = 'PASS'
    #login
    ftp = FTP(myhost,myuser,passw)

    ftp.set_debuglevel(2)
    ftp.voidcmd('TYPE I')
    sock = ftp.transfercmd('RETR ' + filename)
    def background():
        f = open(folder + filename, 'wb')
        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(120)
        ftp.voidcmd('NOOP')
    ftp.quit();


My PROBLEM: FTP.transfercmd("RETR " + filename) defaults to ASCII transfers and Im transferring video so it has to be Binary (hence the ftp.voidcmd('TYPE I) call to force Binary mode).

If I DONT call ftp.voidcmd('TYPE I) the NOOP commands get send successfully and the output is as follows:

*cmd* 'NOOP'
*put* 'NOOP\r\n'
*get* '200 NOOP: data transfer in progress\n'
*resp* '200 NOOP: data transfer in progress'
*cmd* 'NOOP'
*put* 'NOOP\r\n'
*get* '200 NOOP: data transfer in progress\n'
*resp* '200 NOOP: data transfer in progress'
*cmd* 'NOOP'
*put* 'NOOP\r\n'
*get* '200 NOOP: data transfer in progress\n'
*resp* '200 NOOP: data transfer in progress'

etc. But the file is in ASCII and therefor corrupted. If I DO call ftp.voidcmd('TYPE I), The NOOP command only sends once, and the control socket doesnt respond until the transfer completes. If the file is large, the control socket times out as if the NOOPs were never sent...

Very strange, but I am sure its simple. It seems as though the transfercmd() is not splitting the control and data sockets as it is supposed to... and therefore the ftp var is not seperated from the data stream... or something. strange.

Thanks in advance for any advice you can offer.

解决方案

tcpdump confirms that server only sends 226 Transfer complete. after entire file was sent by the server.

I suspect that's part of FTP specification.

In fact, look at retrbinary code in ftplib.py:

    self.voidcmd('TYPE I')
    conn = self.transfercmd(cmd, rest)
    while 1:
        data = conn.recv(blocksize)
        if not data:
            break
        callback(data)
    conn.close()
    return self.voidresp()

The last line expects to get tranfer result (as known to server) only after tranfer is complete.

In fact it seems your code is missing voidresp() bit.

I am not very familiar with ftp, from what I've seen background downloaders like lftp actually open new control connection for each parallel download.

You have a valid concern if your file is really large.

There are many extensions to FTP, there may be something that does what you want.

Alternatively you can make a loop likes this:

pos = 0
while not full file:
    command REST
    download for a while in separate thread
    command ABRT
    wait for separate thread to abort
    pos += length of downloaded chunk

这篇关于ftplib python:NOOP命令在ASCII中不是Binary的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆