FTP (File Transfer Protocol) 是網路上最基礎的檔案傳輸協定之一。雖然現代開發多使用 SFTP 或 HTTP API,但理解 FTP 伺服器的內部運作機制,對於網路程式設計、協定解析與舊系統維護仍具高度教學價值。本文將帶您逐步實作一個支援主動/被動模式、登入驗證、目錄操作、檔案上傳下載的 Java FTP 伺服器。
ServerA 類別建立 ServerSocket 監聽指定 Port,每接受一個 Client 連線,即啟動一條 ClientThread 處理該 Session。
public class ServerA {
public static void main(String[] args) {
final int PORT = 21; // 標準 FTP Port
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
System.out.println("FTP Server started on port " + PORT);
while (true) {
Socket client = serverSocket.accept();
new ClientThread(client, "C:/ftp_root").start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
每個執行緒維護自己的狀態:登入狀態、目前工作目錄、資料通道 Socket 等。核心迴圈讀取指令,轉大寫比對,委派對應處理邏輯。
public class ClientThread extends Thread {
private Socket socket;
private String rootDir;
private boolean loggedIn = false;
private String username;
private Socket dataSocket; // 主動/被動模式建立的資料連線
// 建構子、run() 迴圈、指令分派 switch-case 略
// 關鍵方法:handleUser(), handlePass(), handlePort(), handlePasv()
// handleRetr(), handleStor(), handleList(), handleNlst()
}
Client 傳送 PORT h1,h2,h3,h4,p1,p2,Server 解析 IP 為 h1.h2.h3.h4,Port 為 p1*256 + p2,主動發起 Socket 連線。
Server 建立 ServerSocket 綁定隨機高位 Port,回傳 227 Entering Passive Mode (ip1,ip2,ip3,ip4,p1,p2),等待 Client 連線 accept()。
使用 RandomAccessFile 配合資料通道的 InputStream/OutputStream 進行區塊讀寫 (1024 bytes buffer),支援斷點續傳基礎。
整合 log4j 記錄連線資訊、指令流向、錯誤堆疊,方便除錯與稽核。設定檔 log4j.properties 定義 Console、Daily Rolling File、Error 專屬 Appender。
log4j.jar 在 Classpath。.java 檔案。java ServerA 啟動伺服器。ftp) 連線測試:ftp localhost 21 -> 輸入 root/root -> ls, get test.txt, put local.txt。 親手實作 FTP 伺服器,不僅能深入理解 RFC 959 協定細節,更能訓練 Socket 程式設計、多執行緒併發、狀態機設計等核心能力。完整程式碼已上傳 GitHub (連結略),歡迎 Fork 實驗擴充。