FTP是Internet 上用來傳送文件的協議
在Internet上通過FTP 服務器可以進行文件的上傳(Upload)或下載(Download)
FTP是實時聯機服務
在使用它之前必須是具有該服務的一個用戶(用戶名和口令)
工作時客戶端必須先登錄到作為服務器一方的計算機上
用戶登錄後可以進行文件搜索和文件傳送等有關操作
如改變當前工作目錄
列文件目錄
設置傳輸參數及傳送文件等
使用FTP可以傳送所有類型的文件
如文本文件
二進制可執行文件
圖象文件
聲音文件和數據壓縮文件等
FTP 命令
FTP 的主要操作都是基於各種命令基礎之上的
常用的命令有
◆ 設置傳輸模式
它包括ASCⅡ(文本) 和BINARY 二進制模式
◆ 目錄操作
改變或顯示遠程計算機的當前目錄(cd
dir/ls 命令)
◆ 連接操作
open命令用於建立同遠程計算機的連接
close命令用於關閉連接
◆ 發送操作
put命令用於傳送文件到遠程計算機
mput 命令用於傳送多個文件到遠程計算機
◆ 獲取操作
get命令用於接收一個文件
mget命令用於接收多個文件
編程思路
根據FTP的工作原理
在主函數中建立一個服務器套接字端口
等待客戶端請求
一旦客戶端請求被接受
服務器程序就建立一個服務器分線程
處理客戶端的命令
如果客戶端需要和服務器端進行文件的傳輸
則建立一個新的套接字連接來完成文件的操作
編程技巧說明
主函數設計
在主函數中
完成服務器端口的偵聽和服務線程的創建
我們利用一個靜態字符串變量initDir 來保存服務器線程運行時所在的工作目錄
服務器的初始工作目錄是由程序運行時用戶輸入的
缺省為C盤的根目錄
具體的代碼如下
public class ftpServer extends Thread{
private Socket socketClient;
private int counter;
private static String initDir;
public static void main(String[] args){
if(args
length !=
) {
initDir = args[
];
}else{ initDir =
c:
;}
int i =
;
try{
System
out
println(
ftp server started!
)
//監聽
號端口
ServerSocket s = new ServerSocket(
)
for(
){
//接受客戶端請求
Socket incoming = s
accept()
//創建服務線程
new ftpServer(incoming
i)
start()
i++;
}
}catch(Exception e){}
}
線程類的設計
線程類的主要設計都是在run()方法中實現
用run()方法得到客戶端的套接字信息
根據套接字得到輸入流和輸出流
向客戶端發送歡迎信息
FTP命令的處理
(
) 訪問控制命令
◆ user name(user) 和 password (pass) 命令處理代碼如下
if(str
startsWith(
USER
)){
user = str
substring(
)
user = user
trim()
out
println(
Password
)
}
if(str
startsWith(
PASS
))
out
println(
User
+user+
logged in
)
User 命令和 Password 命令分別用來提交客戶端用戶輸入的用戶名和口令
◆ CWD (CHANGE WORKING DIRECTORY) 命令處理代碼如下
if(str
startsWith(
CWD
)){
String str
= str
substring(
)
dir = dir+
/
+str
trim()
out
println(
CWD command succesful
)
}
該命令改變工作目錄到用戶指定的目錄
◆ CDUP (CHANGE TO PARENT DIRECTORY) 命令處理代碼如下
if(str
startsWith(
CDUP
)){
int n = dir
lastIndexOf(
/
)
dir = dir
substring(
n)
out
println(
CWD command succesful
)
}
該命令改變當前目錄為上一層目錄
◆ QUIT命令處理代碼如下
if(str
startsWith(
QUIT
)) {
out
println(
GOOD BYE
)
done = true;}
該命令退出及關閉與服務器的連接
輸出GOOD BYE
(
) 傳輸參數命令
◆ Port命令處理代碼如下
if(str
startsWith(
PORT
)) {
out
println(
PORT command successful
)
int i = str
length()
;
int j = str
lastIndexOf(
)
int k = str
lastIndexOf(
j
)
String str
str
;str
=
;
str
=
;for(int l=k+
;
lstr
= str
+ str
charAt(l)
}
for(int l=j+
;l<=i;l++){
str
= str
+ str
charAt(l)
}
tempPort = Integer
parseInt(str
) *
*
+Integer
parseInt(str
)
}
使用該命令時
客戶端必須發送客戶端用於接收數據的
位IP 地址和
位 的TCP 端口號
這些信息以
位為一組
使用十進制傳輸
中間用逗號隔開
◆ TYPE命令處理代碼如下
if(str
startsWith(
TYPE
)){
out
println(
type set
)
}
TYPE 命令用來完成類型設置
(
) FTP 服務命令
◆ RETR (RETEIEVE) 和 STORE (STORE)命令處理的代碼
if(str
startsWith(
RETR
)){
out
println(
Binary data connection
)
str = str
substring(
)
str = str
trim()
RandomAccessFile outFile = newRandomAccessFile(dir+
/
+str
r
)
Socket tempSocket = new Socket(host
tempPort)
OutputStream outSocket= tempSocket
getOutputStream()
byte byteBuffer[]= new byte[
];
int amount;
try{
while((amount = outFile
read(byteBuffer)) !=
){
outSocket
write(byteBuffer
amount)
}
outSocket
close()
out
println(
transfer complete
)
outFile
close()
tempSocket
close()
}
catch(IOException e){}
}
if(str
startsWith(
STOR
)){
out
println(
Binary data connection
)
str = str
substring(
)
str = str
trim()
RandomAccessFile inFile = newRandomAccessFile(dir+
/
+str
rw
)
Socket tempSocket = new Socket(host
tempPort)
InputStream inSocket= tempSocket
getInputStream()
byte byteBuffer[] = new byte[
];
int amount;
try{
while((amount =inSocket
read(byteBuffer) )!=
){
inFile
write(byteBuffer
amount)
}
inSocket
close()
out
println(
transfer complete
)
inFile
close()
tempSocket
close()
}
catch(IOException e)
{}
}
文件傳輸命令包括從服務器中獲得文件RETR和向服務器中發送文件STOR
這兩個命令的處理非常類似
處理RETR命令時
首先得到用戶要獲得的文件的名稱
根據名稱創建一個文件輸入流
然後和客戶端建立臨時套接字連接
並得到一個輸出流
隨後
將文件輸入流中的數據讀出並借助於套接字輸出流發送到客戶端
傳輸完畢以後
關閉流和臨時套接字
STOR 命令的處理也是同樣的過程
只是方向正好相反
◆ DELE (DELETE)命令處理代碼如下
if(str
startsWith(
DELE
)){
str = str
substring(
)
str = str
trim()
File file = new File(dir
str)
boolean del = file
delete()
out
println(
delete command successful
)
}
DELE 命令用於刪除服務器上的指定文件
◆ LIST命令處理代碼如下
if(str
startsWith(
LIST
)) {
try{
out
println(
ASCII data
)
Socket tempSocket = new Socket(host
tempPort)
PrintWriter out
= new PrintWriter(tempSocket
getOutputStream()
true)
File file = new File(dir)
String[]
dirStructure = new String[
];
dirStructure= file
list()
String strType=
;
for(int i=
;iif( dirStructure[i]
indexOf(
) ==
) {
strType =
d
;}
else{
strType =
;}
out
println(strType+dirStructure[i])
}
tempSocket
close()
out
println(
transfer complete
)
}
catch(IOException e)
{}
LIST 命令用於向客戶端返回服務器中工作目錄下的目錄結構
包括文件和目錄的列表
處理這個命令時
先創建一個臨時的套接字向客戶端發送目錄信息
這個套接字的目的端口號缺省為
然後為當前工作目錄創建File 對象
利用該對象的list()方法得到一個包含該目錄下所有文件和子目錄名稱的字符串數組
然後根據名稱中是否含有文件名中特有的
來區別目錄和文件
最後
將得到的名稱數組通過臨時套接字發送到客戶端
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26847.html