使用Socket通信實(shí)現(xiàn)FTP客戶端程序_第1頁
使用Socket通信實(shí)現(xiàn)FTP客戶端程序_第2頁
使用Socket通信實(shí)現(xiàn)FTP客戶端程序_第3頁
使用Socket通信實(shí)現(xiàn)FTP客戶端程序_第4頁
使用Socket通信實(shí)現(xiàn)FTP客戶端程序_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、FTP 概述文件傳輸協(xié)議(FTP )作為網(wǎng)絡(luò)共享文件的傳輸協(xié)議,在網(wǎng)絡(luò)應(yīng)用軟件中具有廣泛的應(yīng)用。FTP 的目標(biāo)是提高文件的共享性和可靠高效地傳送數(shù)據(jù)。在傳輸文件時, FTP客戶端程序先與服務(wù)器建立連接,然后向服務(wù)器發(fā)送命令。服務(wù)器收到命令后給予響應(yīng),并執(zhí)行命令。FTP 協(xié)議與操作系統(tǒng)無關(guān),任何操作系統(tǒng)上的程序只要符合FTP 協(xié)議,就可以相互傳輸數(shù)據(jù)。 本文主要基于LINUX平臺,對 FTP客戶端的實(shí)現(xiàn)原理進(jìn)行詳盡的解釋并闡述如何使用C 語言編寫一個簡單的FTP客戶端?;仨撌譌TP 協(xié)議相比其他協(xié)議,如HTTP協(xié)議, FTP 協(xié)議要復(fù)雜一些。與一般的C/S 應(yīng)用不同點(diǎn)在于一般的C/S 應(yīng)用程序一

2、般只會建立一個Socket連接,這個連接同時處理服務(wù)器端和客戶端的連接命令和數(shù)據(jù)傳輸。而FTP 協(xié)議中將命令與數(shù)據(jù)分開傳送的方法提高了效率。FTP使用2 個端口,一個數(shù)據(jù)端口和一個命令端口(也叫做控制端口)。這兩個端口一般是21 (命令端口)和20 (數(shù)據(jù)端口)??刂芐ocket用來傳送命令,數(shù)據(jù)Socket 是用于傳送數(shù)據(jù)。每一個 FTP 命令發(fā)送之后, FTP 服務(wù)器都會返回一個字符串,其中包括一個響應(yīng)代碼和一些說明信息。其中的返回碼主要是用于判斷命令是否被成功執(zhí)行了。命令端口一般來說,客戶端有一個Socket用來連接FTP服務(wù)器的相關(guān)端口,它負(fù)責(zé)FTP 命令的發(fā)送和接收返回的響應(yīng)信息。一

3、些操作如“登錄 ”、“改變目錄 ”、“刪除文件 ”,依靠這個連接發(fā)送命令就可完成。數(shù)據(jù)端口對于有數(shù)據(jù)傳輸?shù)牟僮?,主要是顯示目錄列表,上傳、下載文件,我們需要依靠另一個Socket 來完成。如果使用被動模式,通常服務(wù)器端會返回一個端口號??蛻舳诵枰昧黹_一個Socket來連接這個端口,然后我們可根據(jù)操作來發(fā)送命令,數(shù)據(jù)會通過新開的一個端口傳輸。如果使用主動模式,通??蛻舳藭l(fā)送一個端口號給服務(wù)器端,并在這個端口監(jiān)聽。服務(wù)器需要連接到客戶端開啟的這個數(shù)據(jù)端口,并進(jìn)行數(shù)據(jù)的傳輸。下面對FTP 的主動模式和被動模式做一個簡單的介紹。主動模式(PORT)主動模式下,客戶端隨機(jī)打開一個大于1024的端口向

4、服務(wù)器的命令端口P ,即 21 端口,發(fā)起連接,同時開放N +1端口監(jiān)聽,并向服務(wù)器發(fā)出“port N+1 ”命令,由服務(wù)器從它自己的數(shù)據(jù)端口(20)主動連接到客戶端指定的數(shù)據(jù)端口(N+1) 。FTP的客戶端只是告訴服務(wù)器自己的端口號,讓服務(wù)器來連接客戶端指定的端口。對于客戶端的防火墻來說,這是從外部到內(nèi)部的連接,可能會被阻塞。被動模式(PASV)為了解決服務(wù)器發(fā)起到客戶的連接問題,有了另一種FTP連接方式,即被動方式。命令連接和數(shù)據(jù)連接都由客戶端發(fā)起,這樣就解決了從服務(wù)器到客戶端的數(shù)據(jù)端口的連接被防火墻過濾的問題。被動模式下,當(dāng)開啟一個FTP 連接時,客戶端打開兩個任意的本地端口(N 102

5、4 和 N+1)。第一個端口連接服務(wù)器的21 端口,提交PASV命令。然后,服務(wù)器會開啟一個任意的端口(P 1024 ),返回如 “227 entering passive mode (127,0,0,1,4,18)”。 它返回了227 開頭的信息,在括號中有以逗號隔開的六個數(shù)字,前四個指服務(wù)器的地址,最后兩個,將倒數(shù)第二個乘256再加上最后一個數(shù)字,這就是FTP 服務(wù)器開放的用來進(jìn)行數(shù)據(jù)傳輸?shù)亩丝?。如得?27 entering passive mode (h1,h2,h3,h4,p1,p2),那么端口號是 p1*256+p2 ,ip地址為 h1.h2.h3.h4 。這意味著在服務(wù)器上有一個

6、端口被開放??蛻舳耸盏矫钊〉枚丝谔栔?會通過 N+1 號端口連接服務(wù)器的端口P,然后在兩個端口之間進(jìn)行數(shù)據(jù)傳輸。主要用到的 FTP命令FTP 每個命令都有3 到4 個字母組成,命令后面跟參數(shù),用空格分開。每個命令都以rn 結(jié)束。要下載或上傳一個文件,首先要登入FTP服務(wù)器,然后發(fā)送命令,最后退出。這個過程中,主要用到的命令有USER 、PASS 、SIZE 、REST 、CWD 、RETR 、PASV 、PORT 、QUIT 。USER:指定用戶名。通常是控制連接后第一個發(fā)出的命令。“ USER gaoleyi n”: 用戶名為 gaoleyi 登錄。PASS:指定用戶密碼。該命令緊跟US

7、ER命令后。 “ PASSn”:密碼為 gaoleyi 。SIZE:從服務(wù)器上返回指定文件的大小?!?SIZE file.txtn”:如果 file.txt 文件存在,則返回該文件的大小。CWD:改變工作目錄。如:“ CWD dirnamen”。PASV:讓服務(wù)器在數(shù)據(jù)端口監(jiān)聽,進(jìn)入被動模式。如:“ PASV n”。PORT:告訴 FTP 服務(wù)器客戶端監(jiān)聽的端口號,讓FTP 服務(wù)器采用主動模式連接客戶端。如:“ PORT h1,h2,h3,h4,p1,p2 。”RETR:下載文件。 “ REn”:下載文件file.txt 。STOR:上傳文件。 “ STOR file.txtn”:上傳文件fi

8、le.txt 。REST:該命令并不傳送文件,而是略過指定點(diǎn)后的數(shù)據(jù)。此命令后應(yīng)該跟其它要求文件傳輸?shù)腇TP 命令。 “ REST 100n”:重新指定文件傳送的偏移量為100 字節(jié)。QUIT:關(guān)閉與服務(wù)器的連接。FTP 響應(yīng)碼客戶端發(fā)送FTP 命令后,服務(wù)器返回響應(yīng)碼。響應(yīng)碼用三位數(shù)字編碼表示:第一個數(shù)字給出了命令狀態(tài)的一般性指示,比如響應(yīng)成功、失敗或不完整。第二個數(shù)字是響應(yīng)類型的分類,如2 代表跟連接有關(guān)的響應(yīng),3 代表用戶認(rèn)證。第三個數(shù)字提供了更加詳細(xì)的信息。第一個數(shù)字的含義如下:1 表示服務(wù)器正確接收信息,還未處理。2 表示服務(wù)器已經(jīng)正確處理信息。3 表示服務(wù)器正確接收信息,正在處理。

9、4 表示信息暫時錯誤。5 表示信息永久錯誤。第二個數(shù)字的含義如下:0 表示語法。1 表示系統(tǒng)狀態(tài)和信息。2 表示連接狀態(tài)。3 表示與用戶認(rèn)證有關(guān)的信息。4 表示未定義。1 / 85 表示與文件系統(tǒng)有關(guān)的信息。Socket編程的幾個重要步驟Socket客戶端編程主要步驟如下:1. socket() 創(chuàng)建一個 Socket2. connect() 與服務(wù)器連接3. write() 和 read() 進(jìn)行會話4. close() 關(guān)閉 Socket Socket 服務(wù)器端編程主要步驟如下:1. socket() 創(chuàng)建一個 Socket2. bind()3. listen() 監(jiān)聽4. accept(

10、) 接收連接的請求5. write() 和 read() 進(jìn)行會話6. close() 關(guān)閉 Socket回頁首實(shí)現(xiàn) FTP客戶端上傳下載功能下面讓我們通過一個例子來對FTP 客戶端有一個深入的了解。本文實(shí)現(xiàn)的FTP客戶端有下列功能:1. 客戶端和 FTP 服務(wù)器建立 Socket 連接。2.向服務(wù)器發(fā)送USER 、PASS命令登錄FTP 服務(wù)器。3. 使用 PASV 命令得到服務(wù)器監(jiān)聽的端口號,建立數(shù)據(jù)連接。4. 使用 RETR/STOR 命令下載 /上傳文件。5. 在下載完畢后斷開數(shù)據(jù)連接并發(fā)送QUIT 命令退出。本例中使用的FTP服務(wù)器為filezilla 。在整個交互的過程中,控制連接

11、始終處于連接的狀態(tài),數(shù)據(jù)連接在每傳輸一個文件時先打開,后關(guān)閉??蛻舳撕虵TP 服務(wù)器建立Socket連接當(dāng)客戶端與服務(wù)器建立連接后,服務(wù)器會返回220的響應(yīng)碼和一些歡迎信息。圖 1. 客戶端連接到服務(wù)器端清單1. 客戶端連接到FTP服務(wù)器,接收歡迎信息SOCKET control_sock;struct hostent *hp;struct sockaddr_in server;memset(&server, 0, sizeof(struct sockaddr_in);/*初始化 socket */control_sock = socket(AF_INET, SOCK_STREAM, 0);h

12、p = gethostbyname(server_name);memcpy(&server.sin_addr, hp-h_addr, hp-h_length);server.sin_family = AF_INET;server.sin_port = htons(port);/*連接到服務(wù)器端*/connect(control_sock,(struct sockaddr *)&server, sizeof(server);/*客戶端接收服務(wù)器端的一些歡迎信息*/read(control_sock, read_buf, read_len);2 / 8客戶端登錄FTP 服務(wù)器當(dāng)客戶端發(fā)送用戶名和密

13、碼,服務(wù)器驗(yàn)證通過后,會返回230 的響應(yīng)碼。然后客戶端就可以向服務(wù)器端發(fā)送命令了。圖 2. 客戶端登錄FTP服務(wù)器清單2. 客戶端發(fā)送用戶名和密碼,登入FTP服務(wù)器/*命令 ”n” */sprintf(send_buf,USER %srn,username);/* 客戶端發(fā)送用戶名到服務(wù)器端*/write(control_sock, send_buf, strlen(send_buf);/*客戶端接收服務(wù)器的響應(yīng)碼和信息,正常為”331 User name okay, need password.”*/read(control_sock, read_buf, read_len);/*命令 ”

14、PASS passwordrn” */sprintf(send_buf,PASS %srn,password);/*客戶端發(fā)送密碼到服務(wù)器端*/write(control_sock, send_buf, strlen(send_buf);/*客戶端接收服務(wù)器的響應(yīng)碼和信息,正常為”230 User logged in, proceed.”*/read(control_sock, read_buf, read_len);客戶端讓FTP 服務(wù)器進(jìn)入被動模式當(dāng)客戶端在下載/上傳文件前,要先發(fā)送命令讓服務(wù)器進(jìn)入被動模式。服務(wù)器會打開數(shù)據(jù)端口并監(jiān)聽。并返回響應(yīng)碼227和數(shù)據(jù)連接的端口號。圖 3. 客戶端

15、讓服務(wù)器進(jìn)入被動模式清單3. 讓服務(wù)器進(jìn)入被動模式,在數(shù)據(jù)端口監(jiān)聽/*命令 ”PASVrn” */sprintf(send_buf,PASVrn);/*客戶端告訴服務(wù)器用被動模式*/3 / 8write(control_sock, send_buf, strlen(send_buf);/* 客戶端接收服務(wù)器的響應(yīng)碼和新開的端口號,*正常為 ”227 Entering passive mode ()”*/read(control_sock, read_buf, read_len);客戶端通過被動模式下載文件當(dāng)客戶端發(fā)送命令下載文件。服務(wù)器會返回響應(yīng)碼150 ,并向數(shù)據(jù)連接發(fā)送文件內(nèi)容。圖 4.

16、客戶端從FTP 服務(wù)器端下載文件清單4. 客戶端連接到FTP服務(wù)器的數(shù)據(jù)端口并下載文件/*連接服務(wù)器新開的數(shù)據(jù)端口*/connect(data_sock,(struct sockaddr *)&server, sizeof(server);/*命令 ”CWD dirnamern” */sprintf(send_buf,CWD %srn, dirname);/*客戶端發(fā)送命令改變工作目錄*/write(control_sock, send_buf, strlen(send_buf);/*客戶端接收服務(wù)器的響應(yīng)碼和信息,正常為”250 Command okay.”*/read(control_so

17、ck, read_buf, read_len);/*命令 ”SIZE filenamern” */sprintf(send_buf,SIZE %srn,filename);/*客戶端發(fā)送命令從服務(wù)器端得到下載文件的大小*/write(control_sock, send_buf, strlen(send_buf);/*客戶端接收服務(wù)器的響應(yīng)碼和信息,正常為”213 ” */read(control_sock, read_buf, read_len);/*命令 ”RETR filenamern” */sprintf(send_buf,RETR %srn,filename);/*客戶端發(fā)送命令從服

18、務(wù)器端下載文件*/write(control_sock, send_buf, strlen(send_buf);/*客戶端接收服務(wù)器的響應(yīng)碼和信息,正常為”150 Opening data connection.”*/read(control_sock, read_buf, read_len);/*客戶端創(chuàng)建文件*/file_handle = open(disk_name, CRFLAGS, RWXALL);4 / 8for( ; ; ) . ./*客戶端通過數(shù)據(jù)連接從服務(wù)器接收文件內(nèi)容*/read(data_sock, read_buf, read_len);/*客戶端寫文件*/write(

19、file_handle, read_buf, read_len);. ./*客戶端關(guān)閉文件*/rc = close(file_handle);客戶端退出服務(wù)器當(dāng)客戶端下載完畢后,發(fā)送命令退出服務(wù)器,并關(guān)閉連接。服務(wù)器會返回響應(yīng)碼200 。圖 5. 客戶端從FTP服務(wù)器退出清單5. 客戶端關(guān)閉數(shù)據(jù)連接,退出FTP服務(wù)器并關(guān)閉控制連接/*客戶端關(guān)閉數(shù)據(jù)連接*/close(data_sock);/*客戶端接收服務(wù)器的響應(yīng)碼和信息,正常為”226 Transfer complete.” */read(control_sock, read_buf, read_len);/*命令 ”QUITn” */sp

20、rintf(send_buf,QUITrn);/*客戶端將斷開與服務(wù)器端的連接*/write(control_sock, send_buf, strlen(send_buf);/*客戶端接收服務(wù)器的響應(yīng)碼,正常為”200 Closes connection.” */read(control_sock, read_buf, read_len);/*客戶端關(guān)閉控制連接*/close(control_sock);至此,下載文件已經(jīng)完成。需要注意的是發(fā)送FTP命令的時候,在命令后要緊跟“rn ”,否則服務(wù)器不會返回信息?;剀嚀Q行符號“ n” 是FTP 命令的結(jié)尾符號,當(dāng)服務(wù)器接收到這個符號時,認(rèn)為客戶

21、端發(fā)送的命令已經(jīng)結(jié)束,開始處理。否則會繼續(xù)等待。讓我們來看一下FTP 服務(wù)器這一端的響應(yīng)情況:清單6. 客戶端下載文件時,F(xiàn)TP服務(wù)器的響應(yīng)輸出(not logged in) () Connected, sending welcome message.(not logged in) () 220-FileZilla Server version 0.9.36 beta(not logged in) () 220 hello gaoleyi(not logged in) () USER gaoleyi(not logged

22、in) () 331 Password required for gaoleyi(not logged in) () PASS *gaoleyi () 230 Logged ongaoleyi () PWD5 / 8gaoleyi () 257 / is current directory.gaoleyi () SIZE file.txtgaoleyi () 213 4096gaoleyi ()PASVgaoleyi () 227 E

23、ntering Passive Mode (127,0,0,1,13,67)gaoleyi ()RETR file.txtgaoleyi () 150 Connection acceptedgaoleyi () 226 Transfer OKgaoleyi () QUITgaoleyi () 221 Goodbye首先,服務(wù)器準(zhǔn)備就緒后返回220 ??蛻舳私邮盏椒?wù)器端返回的響應(yīng)碼后,相繼發(fā)送“USER username”和 “PASS password” 命令登錄。隨后,服務(wù)器返回的響應(yīng)碼為 230 開

24、頭,說明客戶端已經(jīng)登入了。這時,客戶端發(fā)送PASV命令讓服務(wù)器進(jìn)入被動模式。服務(wù)器返回如“227 Entering Passive Mode (127,0,0,1,13,67),”客戶端從中得到端口號,然后連接到服務(wù)器的數(shù)據(jù)端口。接下來,客戶端發(fā)送下載命令,服務(wù)器會返回響應(yīng)碼150 ,并從數(shù)據(jù)端口發(fā)送數(shù)據(jù)。最后,服務(wù)器返回“226 transfercomplete ”,表明數(shù)據(jù)傳輸完成。需要注意的是,客戶端不要一次發(fā)送多條命令,例如我們要打開一個目錄并且顯示這個目錄,我們得發(fā)送CWD dirname ,PASV ,LIST 。在發(fā)送完 CWD dirname 之后等待響應(yīng)代碼, 然后再發(fā)送后面

25、一條。 當(dāng) PASV 返回之后, 我們打開另一個 Socket連接到相關(guān)端口上。 然后發(fā)送 LIST ,返回 125 之后在開始接收數(shù)據(jù), 最后返回 226表明完成。在傳輸多個文件的過程中,需要注意的是每次新的傳輸都必須重新使用PASV 獲取新的端口號,接收完數(shù)據(jù)后應(yīng)該關(guān)閉該數(shù)據(jù)連接,這樣服務(wù)器才會返回一個2XX 成功的響應(yīng)。然后客戶端可以繼續(xù)下一個文件的傳輸。上傳文件與下載文件相比,登入驗(yàn)證和切換被動模式都如出一轍,只需要改變發(fā)送到服務(wù)器端的命令,并通過數(shù)據(jù)連接發(fā)送文件內(nèi)容??蛻舳送ㄟ^被動模式向服務(wù)器上傳文件當(dāng)客戶端發(fā)送命令上傳文件,服務(wù)器會從數(shù)據(jù)連接接收文件。圖 6. 客戶端連接到FTP服

26、務(wù)器的數(shù)據(jù)端口并上傳文件客戶端通過主動模式向服務(wù)器上傳文件到目前為止,本文介紹的都是客戶端用被動模式進(jìn)行文件的上傳和下載。下面將介紹客戶端用主動模式下載文件。6 / 8圖 7. 用主動模式從FTP服務(wù)器下載文件清單 7.用主動模式從 FTP服務(wù)器下載文件的示例C 程序. .SOCKET data_sock;data_sock = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in name;name.sin_family = AF_INET;name.sin_addr.s_addr = htons(INADDR_ANY);server_port

27、 = p1*256+p2;length = sizeof(name);name.sin_port = htons(server_port);bind(server_sock, (struct sockaddr *)&name, length);struct sockaddr_in client_name;length = sizeof(client_name);/*客戶端開始監(jiān)聽端口p1*256+p2 */listen(server_sock, 64);/*命令 ”PORT rn” */sprintf(send_buf,PORT 1287,0,0,1,%d,%drn, p1, p2);writ

28、e(control_sock, send_buf,strlen(send_buf);/*客戶端接收服務(wù)器的響應(yīng)碼和信息,正常為”200 Port command successful” */read(control_sock, read_buf, read_len);sprintf(send_buf,RETR filename.txtrn);write(control_sock, send_buf, strlen(send_buf);/*客戶端接收服務(wù)器的響應(yīng)碼和信息,正常為”150 Opening data channel for file transfer.” */read(control

29、_sock, read_buf, read_len);/* ftp客戶端接受服務(wù)器端的連接請求*/data_sock = accept(server_sock,(struct sockaddr *)&client_name, &length);. .file_handle = open(disk_name, ROFLAGS, RWXALL);for( ; ; ) . .read(data_sock, read_buf, read_len);write(file_handle, read_buf, read_len);. .close(file_handle);7 / 8客戶端通過PORT命令告

30、訴服務(wù)器連接自己的p1*256+p2端口。隨后在這個端口進(jìn)行監(jiān)聽,等待FTP服務(wù)器連接上來,再通過這個數(shù)據(jù)端口來傳輸文件。PORT方式在傳送數(shù)據(jù)時,F(xiàn)TP客戶端其實(shí)就相當(dāng)于一個服務(wù)器端,由FTP 服務(wù)器主動連接自己。斷點(diǎn)續(xù)傳由于網(wǎng)絡(luò)不穩(wěn)定,在傳輸文件的過程中,可能會發(fā)生連接斷開的情況,這時候需要客戶端支持?jǐn)帱c(diǎn)續(xù)傳的功能,下次能夠從上次終止的地方開始接著傳送。需要使用命令REST 。如果在斷開連接前,一個文件已經(jīng)傳輸了512 個字節(jié)。則斷點(diǎn)續(xù)傳開始的位置為512 ,服務(wù)器會跳過傳輸文件的前512字節(jié)。清單8. 從 FTP服務(wù)器斷點(diǎn)續(xù)傳下載文件. ./*命令 ”REST offsetrn” */sprintf(send_buf,REST %ldrn, offset);/*客戶端發(fā)送命令指定下載文件的偏移量*/write(control_sock, send_buf, strlen(send_buf);/*客戶端接收服務(wù)器的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論