嗯,这个星期就不写英文了,也不用粤语了,本来星期六只是想回来公司轻轻地写篇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