逯昌浩
摘要:FTP是常用的網(wǎng)絡(luò)功能,Java語(yǔ)言有很強(qiáng)的網(wǎng)絡(luò)編程功能。使用Java語(yǔ)言開(kāi)發(fā)FTP客戶端程序很有實(shí)用價(jià)值。文章介紹了FTP協(xié)議的功能特點(diǎn)和FTP客戶端的常用命令,闡述了如何使用Java程序設(shè)計(jì)語(yǔ)言來(lái)實(shí)現(xiàn)FTP客戶端程序功能,并給出了關(guān)鍵命令的實(shí)現(xiàn)代碼。實(shí)踐證明,用Java語(yǔ)言編寫(xiě)的FTP客戶端程序效果良好。
關(guān)鍵詞:FTP;Java;網(wǎng)絡(luò);文件傳輸;線程
中圖分類號(hào):TP311文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2009)14-3697-03
Design of FTP Client Program Based on Java
LU Chang-hao
(Shandong Vocational College of Industry, Zibo 256414, China)
Abstract: FTP is a useful function on the Internet. Java language is high-powered in network program. It is available to design FTP client program by using Java language. In this article, the main functions of FTP protocol and the important commands in FTP client are introduced; the implement of FTP client program is discussed; the pivotal codes are given. The effort is well proved in the practices.
Key words: FTP; Java; network; file transfer; thread
1 引言
FTP(File Transfer Protocol),是文件傳輸協(xié)議的簡(jiǎn)稱,用于在Internet上控制文件的雙向傳輸。用戶在Internet上通過(guò)FTP服務(wù)器可以進(jìn)行文件的上傳(Upload)或下載(Download),也可以通過(guò)它把自己的PC機(jī)與世界各地所有運(yùn)行FTP協(xié)議的服務(wù)器相連,訪問(wèn)服務(wù)器上的大量資源。Java語(yǔ)言支持Internet應(yīng)用的開(kāi)發(fā),在基本的Java應(yīng)用編程接口中有網(wǎng)絡(luò)應(yīng)用編程接口(java.net),提供了用于網(wǎng)絡(luò)應(yīng)用編程的類庫(kù)。Java語(yǔ)言支持多個(gè)線程的同時(shí)執(zhí)行和多線程之間的同步機(jī)制,提供了安全機(jī)制以增強(qiáng)在網(wǎng)絡(luò)環(huán)境中的安全性。因此使用Java語(yǔ)言開(kāi)發(fā)FTP client(客戶端)程序是一個(gè)合適的選擇。本文中就如何使用Java語(yǔ)言實(shí)現(xiàn)FTP客戶端程序進(jìn)行了探討。
2 基于Java語(yǔ)言的FTP Client程序設(shè)計(jì)
2.1 FTP的特點(diǎn)
FTP是實(shí)時(shí)聯(lián)機(jī)服務(wù),在使用它之前必須是具有該服務(wù)的一個(gè)用戶(用戶名和口令),工作時(shí)客戶端必須先登錄到作為服務(wù)器一方的計(jì)算機(jī)上,用戶登錄后可以進(jìn)行文件搜索和文件傳送等有關(guān)操作,如改變當(dāng)前工作目錄、列文件目錄、設(shè)置傳輸參數(shù)及傳送文件等。
FTP有兩種使用模式:主動(dòng)和被動(dòng)。主動(dòng)模式要求客戶端和服務(wù)器端同時(shí)打開(kāi)并且監(jiān)聽(tīng)一個(gè)端口以建立連接。在這種情況下,客戶端由于安裝了防火墻會(huì)產(chǎn)生一些問(wèn)題。所以,創(chuàng)立了被動(dòng)模式。被動(dòng)模式只要求服務(wù)器端產(chǎn)生一個(gè)監(jiān)聽(tīng)相應(yīng)端口的進(jìn)程,這樣就可以繞過(guò)客戶端安裝了防火墻的問(wèn)題。
FTP 的主要操作都是基于各種命令基礎(chǔ)之上的。常用的命令有:
1) 設(shè)置傳輸模式,它包括ASCⅡ(文本)和BINARY二進(jìn)制模式。
2) 目錄操作,改變或顯示遠(yuǎn)程計(jì)算機(jī)的當(dāng)前目錄(cd、dir、ls命令)。
3) 連接操作,open命令用于建立同遠(yuǎn)程計(jì)算機(jī)的連接;close命令用于關(guān)閉連接。
4) 發(fā)送操作,put命令用于傳送文件到遠(yuǎn)程計(jì)算機(jī);mput 命令用于傳送多個(gè)文件到遠(yuǎn)程計(jì)算機(jī)。
5) 獲取操作,get命令用于接收一個(gè)文件;mget命令用于接收多個(gè)文件。
6) 退出操作,BYE命令。
2.2 編程思路
根據(jù)FTP的工作原理,在主函數(shù)中建立一個(gè)服務(wù)器套接字端口,等待客戶端請(qǐng)求,一旦客戶端請(qǐng)求被接受,服務(wù)器程序就建立一個(gè)服務(wù)器分線程,處理客戶端的命令。如果客戶端需要和服務(wù)器端進(jìn)行文件的傳輸,則建立一個(gè)新的套接字連接來(lái)完成文件的操作。編程技巧說(shuō)明如下:
2.2.1 主函數(shù)設(shè)計(jì)
在主函數(shù)中,完成服務(wù)器端口的偵聽(tīng)和服務(wù)線程的創(chuàng)建。利用一個(gè)靜態(tài)字符串變量initDir 來(lái)保存服務(wù)器線程運(yùn)行時(shí)所在的工作目錄。服務(wù)器的初始工作目錄是由程序運(yùn)行時(shí)用戶輸入的,缺省為C盤(pán)的根目錄。關(guān)鍵代碼如下:
try
{ServerSocket s = new ServerSocket(21); //監(jiān)聽(tīng)21號(hào)端口
for(;;) {
Socket incoming = s.accept(); //接受客戶端請(qǐng)求
new ftpServer(incoming,i).start(); //創(chuàng)建服務(wù)線程
i++; }
}catch(Exception e)
{}
2.2.2 線程類的設(shè)計(jì)
在Java中,根據(jù)多線程應(yīng)用程序繼承或?qū)崿F(xiàn)對(duì)象的不同可以采用兩種方式:一種是應(yīng)用程序的并發(fā)運(yùn)行對(duì)象直接繼承Java的線程類Thread;另外一種方式是定義并發(fā)執(zhí)行對(duì)象實(shí)現(xiàn)Runnable接口。不管使用哪種方法,線程類的主要設(shè)計(jì)都是在run()方法中實(shí)現(xiàn)。用run()方法得到客戶端的套接字信息,根據(jù)套接字得到輸入流和輸出流,向客戶端發(fā)送歡迎信息。
2.2.3 FTP命令的處理
1) FTP訪問(wèn)控制命令:
User 命令和 Password 命令分別用來(lái)提交客戶端用戶輸入的用戶名和口令。相應(yīng)的username(user) 和 password (pass) 命令處理代碼如下:
if(str.startsWith("USER"))
{user = str.substring(4);
user = user.trim();
out.println("331 Password");}
if(str.startsWith("PASS"))
{out.println("230 User "+user+" logged in.");}
此外,還有CWD命令用來(lái)改變工作目錄到用戶指定的目錄,CDUP命令改變當(dāng)前目錄為上一層目錄和QUIT命令用于退出及關(guān)閉與服務(wù)器的連接,限于篇幅代碼從略。
2) 傳輸參數(shù)命令:
Port命令用于FTP服務(wù)器IP地址和端口號(hào)的傳輸。使用該命令時(shí),客戶端必須發(fā)送客戶端用于接收數(shù)據(jù)的32位IP地址和16位的TCP端口號(hào)。這些信息以8位為一組,使用十進(jìn)制傳輸,中間用逗號(hào)隔開(kāi)。 Port命令處理代碼如下:
if(str.startsWith("PORT"))
{out.println("200 PORT command successful");
int i = str.length() - 1;
int j = str.lastIndexOf(",");
int k = str.lastIndexOf(",",j-1);
String str1,str2;str1="";
str2="";for(int l=k+1;
lstr1 = str2 + str.charAt(l);}
for(int l=j+1;l<=i;l++)
{str2 = str2 + str.charAt(l);}
tempPort = Integer.parseInt(str1) * 16 *16 +Integer.parseInt(str2);}
此外,還有用來(lái)完成類型設(shè)置的TYPE命令,限于篇幅代碼從略。
3) FTP 服務(wù)命令:
文件傳輸命令包括從服務(wù)器中獲得文件RETR和向服務(wù)器中發(fā)送文件STOR,這兩個(gè)命令的處理非常類似。處理RETR命令時(shí),首先得到用戶要獲得的文件的名稱,根據(jù)名稱創(chuàng)建一個(gè)文件輸入流,然后和客戶端建立臨時(shí)套接字連接,并得到一個(gè)輸出流。隨后,將文件輸入流中的數(shù)據(jù)讀出并借助于套接字輸出流發(fā)送到客戶端,傳輸完畢以后,關(guān)閉流和臨時(shí)套接字。STOR 命令的處理也是同樣的過(guò)程,只是方向正好相反。 RETR (RETEIEVE) 命令處理的關(guān)鍵代碼如下(STORE命令類似,代碼從略):
if(str.startsWith("RETR"))
{out.println("150 Binary data connection");
str = str.substring(4);
str = str.trim();
RandomAccessFile outFile = newRandomAccessFile(dir+"/"+str,"r");
Socket tempSocket = new Socket(host,tempPort);
OutputStream outSocket= tempSocket.getOutputStream();
byte byteBuffer[]= new byte[1024];
int amount;
try
{while((amount = outFile.read(byteBuffer)) != -1)
{outSocket.write(byteBuffer, 0, amount);}
outSocket.close();
out.println("226 transfer complete");
outFile.close();
tempSocket.close();}
catch(IOException e){}}
LIST 命令用于向客戶端返回服務(wù)器中工作目錄下的目錄結(jié)構(gòu),包括文件和目錄的列表。處理這個(gè)命令時(shí),先創(chuàng)建一個(gè)臨時(shí)的套接字向客戶端發(fā)送目錄信息。這個(gè)套接字的目的端口號(hào)缺省為1,然后為當(dāng)前工作目錄創(chuàng)建File 對(duì)象,利用該對(duì)象的list()方法得到一個(gè)包含該目錄下所有文件和子目錄名稱的字符串?dāng)?shù)組,然后根據(jù)名稱中是否含有文件名中特有的“.”來(lái)區(qū)別目錄和文件。最后,將得到的名稱數(shù)組通過(guò)臨時(shí)套接字發(fā)送到客戶端。LIST命令處理代碼如下:
if(str.startsWith("LIST"))
{try
{out.println("150 ASCII data");
Socket tempSocket = new Socket(host,tempPort);
PrintWriter out2= new PrintWriter(tempSocket.getOutputStream(),true);
File file = new File(dir);
String[] dirStructure = new String[10];
dirStructure= file.list();
String strType="";
for(int i=0; i<10; i++)
{if( dirStructure[i].indexOf(".") == -1; )
{strType = "d ";}
else
{strType = "- "; }
out2.println(strType+dirStructure[i]); }
tempSocket.close();
out.println("226 transfer complete"); }
catch(IOException e){} }
DELE命令用于刪除服務(wù)器上的指定文件。則DELE (DELETE)命令處理代碼如下:
if(str.startsWith("DELE"))
{str = str.substring(4);
str = str.trim();
File file = new File(dir,str);
boolean del = file.delete();
out.println("250 delete command successful"); }
3 結(jié)論
上文中對(duì)如何使用Java語(yǔ)言實(shí)現(xiàn)FTP客戶端程序進(jìn)行了探討,并給出了關(guān)鍵代碼實(shí)現(xiàn)。實(shí)踐證明,通過(guò)這種方法實(shí)現(xiàn)的FTP客戶端程序?qū)嵱眯Ч己?能夠完成網(wǎng)絡(luò)上的文件傳輸與共享任務(wù)。
參考文獻(xiàn):
[1] 萬(wàn)江平,黃卓明,夏志忠,等.用Java開(kāi)發(fā)的FTP服務(wù)器[J].華南理工大學(xué)學(xué)報(bào):自然科學(xué)版, 2001(8):65-69.
[2] 楊洋,楊濤,武麗.基于Java的計(jì)算機(jī)輔助學(xué)習(xí)系統(tǒng)設(shè)計(jì)[J].微計(jì)算機(jī)信息,2006(21):156-15.
[3] 冀志剛,王祥.用JAVA語(yǔ)言實(shí)現(xiàn)FTP客戶端[J].唐山師范學(xué)院學(xué)報(bào),2006(5):81-82.
[4] 劉沖,張海玥,張衛(wèi)東,等.用Java JDK編寫(xiě)FTP客戶程序[J].計(jì)算機(jī)應(yīng)用,2001(S1):99-100.
[5] 楊淑萍.基于Java的FTP客戶端程序的設(shè)計(jì)與實(shí)現(xiàn)[J].現(xiàn)代計(jì)算機(jī),2005(10):90-91.
[6] 周鳳艷,余華鴻.FTP研究及基于JAVA的客戶端實(shí)現(xiàn)[J].今日科苑,2008(14):198.
[7] 張景葳,萬(wàn)江平,劉尚余.用Java開(kāi)發(fā)FTP代理服務(wù)器[J].計(jì)算機(jī)應(yīng)用研究,2001(5):104-107.
[8] 鄭佳武.基于JavaBean的多文件上載算法[J].臨沂師范學(xué)院學(xué)報(bào),2004(6):109-113.