實現FTP多執行緒下載 (轉)

worldblog發表於2007-12-04
實現FTP多執行緒下載 (轉)[@more@] 

  現在有不少可實現多執行緒.Ants,JetCar等,其實多執行緒下載的原理並不複雜,主要的兩項技術就是多執行緒和斷點下載。中開啟多個執行緒,每個執行緒利用斷點下載,分別下載的不同部分,下載完後合併,就可以了。多執行緒很多書已有介紹,這裡不再重複,關於斷點下載,MFC中提供的CInternetFile類可實現HTTP的斷點下載,但無法實現的斷點下載。因此,我們只好從FTP中的命令入手,自己編寫個FTP類,來實現多執行緒下載。本人編寫的CMultiFTP類(在+IIS5。0下測試成功)已在CSDN發表。

FTP指令的詳細資訊,大家可從/處獲得">處獲得,這裡給大家介紹下與多執行緒下載有關的幾個指令極其格式:

USER〈USERNAME〉:登陸FTP的名,成功返回220;

PASS〈PASS〉:密碼,執行成功返回230;

REST〈POS〉:指定檔案下載的開始位置,執行成功返回350;

SIZE〈FILENAME〉:檔案大小,執行成功返回213;

PASV:建立資料連線,同時取得FTP下載檔案時用的埠號,執行成功返回227;

TYPE:指定下載檔案的型別,引數為I是二進位制檔案,為A是字元檔案,執行成功返回200;

RETR〈FILENAME〉:下載檔案,執行成功返回125;

這些命令中,REST,RETR,SIZE三個命令最關鍵,在後面會給大家更詳細的說明,另外執行FTP命令,FTP伺服器會向客戶端返回一程式碼,命令執行成功的程式碼上面已給出。向伺服器傳送命令,可把命令當作字串向伺服器傳送,如:send(socket,”rest 100rn”,…)(注意:要在命令後加rn)。

在介紹多執行緒下載前,先給大家介紹下連線FTP伺服器和從FTP伺服器下載檔案的過程。連線FTP SERVER很簡單,建立一套接字,指定伺服器的地址和埠號,連線到伺服器,再向它傳送USER和PASS命令,伺服器返回230,就代表登陸成功,並且伺服器和客戶建立了一控制連線。

FTP伺服器下載檔案的過程比較複雜。首先,客戶端要和伺服器建立一資料連線,可用PORT或PASV命令建立資料連線,PORT命令要自己指定一埠號用於下載,PASV命令則由伺服器分配一埠號,客戶端可從伺服器的返回資訊提取埠號,返回資訊的格式為:

(伺服器IP,埠號),本人的程式將使用PASV命令。然後向伺服器傳送RETR命令下載檔案,或先傳送一REST命令指明從哪下載檔案。之後,要建立一新的套接字,連線到資料連線指定的埠,檔案資料就從這個套接字下載。下載完畢後,關閉套接字。

現在進入本篇的精華,實現多執行緒下載。執行完登陸操作後,先傳送“REST 100”命令,測試下伺服器是否支援斷點下載,如返回成功程式碼,就可實現多執行緒下載;然後傳送“SIZE”,取得檔案的大小,根據檔案大小,將檔案分為幾部分,記下各部分的偏移地址,並作為引數,交給各執行緒去下載。在下載執行緒中,先接受主執行緒傳給他的引數(檔名,偏移地址,儲存地址等),再傳送“PASV”命令,建立資料連線,並新建一套接字連線到新的埠;然後根據檔案型別,二進位制檔案傳送“TYPE  I“命令,文字檔案傳送”TYPE  A“命令;之後傳送“REST  〈檔案偏移地址〉”命令,通知伺服器改變將要下載的檔案的開始地址;最後,執行“RETR 〈檔名〉”命令,下載檔案。下載完畢後,編段程式碼合併檔案即可。

在這裡有個問題,就是主執行緒如何得知各下載執行緒已執行完畢。提供了幾種執行緒互斥技術,如CriticalSection,Mutex等,關於他們的詳細資訊,大家可參考各種程式設計書籍,在這裡我推薦使用CriticalSection技術。可以在程式中建立一全域性計數器,在檔案下載前置零,並建立一全域性CriticalSection變數。在下載執行緒中,當檔案下載完畢後,先鎖定全域性CriticalSection變數,之後將計數器加一,再釋放全域性CriticalSection變數。主執行緒中,可建立一定時,定期檢查計數器的值,或讓下載執行緒在下載完畢後主執行緒的某個。這樣,主執行緒就可隨時發現檔案已下載完畢,可合併檔案了。

多執行緒下載的就是這樣,一點都不難。看來掌握某些技術,特別是技術,最好還是從實現原理入手,掌握其最精華的部分,激發自己的靈感,編寫出個優秀軟體。老停留在使用別人的和函式庫的基礎上,你的水平不會有太大提高。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987970/,如需轉載,請註明出處,否則將追究法律責任。

相關文章