0 前言:
ftp客戶端相信大家都用過,那么我們為什么還要用Python寫ftp客戶端呢?
我想有兩個原因:
一是寫出更好的ftp客戶端應用程序,方便大家使用;
二是定制一些特殊服務,例如每天定時下載/上傳某文件;
我還沒能力也沒時間寫出ftp客戶端應用程序,前期先分析一下python寫ftp客戶端的核心部分,即實現上傳和下載的關鍵部分。
首先看一下ftp服務器/客戶端架構:
1 FTP服務器/客戶端
ftp架構
上圖展示了ftp的工作流程:
1.客戶端連接遠程主機上的FTP 服務器。
2.客戶端輸入用戶名和密碼(或“anonymous”和電子郵件地址)。
3.客戶端進行各種文件傳輸和信息查詢操作。
4.客戶端從遠程FTP 服務器退出,結束傳輸。
下面是一段Python偽代碼。
from ftplib import FTP
f = FTP('some.ftp.server')
f.login('anonymous', 'your@email.address')
:
f. quit()
當然,這只是一般情況下的流程。有時,由于網絡兩邊計算機的崩潰或網絡的問題,會導致整個傳輸在完成之前就中斷。
如果客戶端超過15 分鐘(900 秒)還沒有響應,FTP 連接就會超時并中斷。
在底層,FTP 只使用TCP,而不使用UDP。
另外,可以將FTP 看作客戶端/服務器編程中的特殊情況。因為這里的客戶端和服務器都使用兩個套接字來通信:
一個是控制和命令端口(21 號端口),另一個是數據端口(有時是20 號端口),如上圖 所示。
FTP 有兩種模式:主動和被動。只有在主動模式下服務器才使用數據端口。
在服務器把20 號端口設置為數據端口后,它“主動”連接客戶端的數據端口。而在被動模式下,服務器只是告訴客戶端隨機的數據端口號,客戶端必須主動建立數據連接。
2 客戶端FTP 程序示例
#!/usr/bin/env python
# coding=utf-8
import ftplib
import os
import socket
import pdb
HOST = 'ftp.debian.org'
DIRN = 'debian/tools'
FILE = 'loadlin.exe'
def main():
try:
f = ftplib.FTP(HOST)
except (socket.error, socket.gaierror) as e:
print 'ERROR: cannot reach "%s"' % HOST
return
print '*** Connected to host "%s"' % HOST
try:
f.login()
except ftplib.error_perm:
print 'ERROR: cannot login anonymously'
f.quit()
return
print '*** Logged in as "anonymous"'
try:
f.cwd(DIRN)
except ftplib.error_perm:
print 'ERROR: cannot CD to "%s"' % DIRN
f.quit()
return
print '*** changed to "%s" folder' % DIRN
try:
f.retrbinary('RETR %s' % FILE,
open(FILE,'wb').write)
except ftplib.error_perm:
print 'ERROR: cannot read file "%s"' % FILE
os.unlink(FILE)
else:
print '*** Download "%s" to CWD' %FILE
f.quit()
if __name__ == '__main__':
main()
運行結果:
ftp客戶端運行結果:可以看出loadlin.exe文件被更新了。
3 疑問
上面編寫的客戶端代碼對ftp.debian.org
站點可以正常連接,為什么有的ftp服務器明明可以ping通卻無法連接?
ping ftp.python.org
然而,卻無法連接到服務器:
無法連接ftp.python.org
請高人指點!!謝謝!!