架構概覽
- **控制連接**:TCP 連接,發送指令(USER, PASS, RETR, STOR, QUIT)。
- **資料連接**:主動模式(Server 連 Client)或被動模式(Client 連 Server),傳輸檔案內容。
簡易實作步驟(被動模式)
- Client 連接 Server 21 埠,完成登入驗證。
- Client 發送
PASV,Server 回應監聽 IP/埠(如 227 Entering Passive Mode (192,168,1,100,195,10))。
- Client 連接資料埠,發送
RETR filename(下載)或 STOR filename(上傳)。
- Server 透過資料連接傳送/接收檔案二進位內容。
- 傳輸完畢關閉資料連接,控制連接保持等待下一指令。
關鍵代碼片段
Client 發送檔案
// 建立控制連接
SOCKET ctrlSock = socket(AF_INET, SOCK_STREAM, 0);
connect(ctrlSock, (sockaddr*)&serverAddr, sizeof(serverAddr));
// 登入流程略...
// 進入被動模式
send(ctrlSock, "PASV\r\n", 6, 0);
char buf[1024];
recv(ctrlSock, buf, sizeof(buf), 0);
// 解析 buf 取得 dataIp, dataPort
// 建立資料連接
SOCKET dataSock = socket(AF_INET, SOCK_STREAM, 0);
connect(dataSock, (sockaddr*)&dataAddr, sizeof(dataAddr));
// 發送 STOR 指令
char cmd[256];
sprintf(cmd, "STOR %s\r\n", filename);
send(ctrlSock, cmd, strlen(cmd), 0);
// 讀取本地檔案並發送
FILE *fp = fopen(localPath, "rb");
while (!feof(fp)) {
int n = fread(buf, 1, sizeof(buf), fp);
send(dataSock, buf, n, 0);
}
fclose(fp);
closesocket(dataSock);
// 等待控制連接回應 226 Transfer complete
大檔案與斷點續傳
- 自訂簡易協定:分塊傳輸,每塊帶序號、大小、CRC32。
- 支援
REST offset 斷點續傳(FTP 標準指令)。
- 傳輸前後計算 MD5/SHA256 校驗完整性。
建議
- 生產環境**直接使用成熟庫**:
libcurl (C/C++)、Apache Commons Net (Java)、ftplib (Python)。
- 自行實作 FTP 協定細節極多(編碼、模式、防火牆、TLS/SSL),易有安全漏洞。
- 若僅需局域網傳檔,考慮更簡單的 HTTP POST、WebSocket 或原始 TCP + 自訂協定。