嗯,这个星期就不写英文了,也不用粤语了,本来星期六只是想回来公司轻轻地写篇BLOG,然后5点左右去游水,怎料一回来,没错,就是给你分配工作,开心吧。不是说这工作不好玩,而是,就像同事对七11的饭一样,食得多就会腻。下周周末开始我再也不回来陪老板呵呵了。而且今日是入职六个月纪念日XD
OK,今个星期解决最有意义的问题,做了一个对python FTP客户端的patch。
情况是这样的,... 省略十万字 ...,于是,我们就在amazon那个IP分配机制下遇到pasv(passive模式)动态改变我指定的IP的情况,简单Google咗下,目前没有英文资料,更别说中文资料了,去解决这个问题。
这个问题是,就是我们用ftp命令直连,也会
ftp> passive Passive mode on. ftp> list ?Invalid command ftp> ls 227 Entering Passive Mode (x1,x2,x3,x4,196,8).
直至timeout。
用fileZilla可以解决这个问题,但是我要用python,所以呢,经过一轮挖掘,终于知道原因如上所述。
pasv会返回一个IP地址和端口号,其中端口号分大细超,然后amazon就是默默地给我们返回一个内网IP,当然,我们可以设置服务器端固定pasv返回的IP地址,但是我不要,我要在客户端处理,所以就有了以下的代码。
from ftplib import FTP, parse227, parse229 class FTPP(FTP): """FTP patch version""" def __init__(self): self.fix_host = None FTP.__init__(self) def set_pasv(self, val, addr=None): '''Use passive or active mode for data transfers. set_pasv(val, addr=None) With val is False, use the normal PORT mode, With val is False, use the PASV command. addr means to set a fix ip, no using the pasv return ip. ''' self.passiveserver = val self.fix_host = addr def makepasv(self): if self.af == socket.AF_INET: host, port = parse227(self.sendcmd('PASV')) else: host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername()) if self.fix_host is not None: host = self.fix_host return host, port
用法也极其简单,只要在set_pasv的时候加入IP地址,那么他就固定了。
ftp = FTPP() ftp.set_pasv(True, ip) ftp.connect(ip, port, 100) ftp.login(name, passwd) print ftp.getwelcome() ftp.cwd('else') print ftp.nlst()
正考虑要不要给python提交个源码XD