前提
在學習FTP客戶端之前需要學會socket,FTP客戶端與服務器之間的通訊就是使用socket的過程。
思路:
整個過程需要兩個socket,一個用於與服務器端之間的操作,比如輸入賬號密碼、讀取文件大小或者刪除文件之類的操作,另外一個socket用於接收文件內容、一個流;具體流程看下面的流程圖。
流程圖:
FTP命令:
命令 | 描述 |
---|---|
ABOR | 中斷數據連接程序 |
ACCT
|
系統特權帳號 |
ALLO
|
為服務器上的文件存儲器分配字節 |
APPE
|
添加文件到服務器同名文件 |
CDUP
|
改變服務器上的父目錄 |
CWD
|
改變服務器上的工作目錄 |
DELE
|
刪除服務器上的指定文件 |
HELP |
返回指定命令信息 |
LIST
|
如果是文件名列出文件信息,如果是目錄則列出文件列表 |
MODE
|
傳輸模式(S=流模式,B=塊模式,C=壓縮模式) |
MKD
|
在服務器上建立指定目錄 |
NLST
|
列出指定目錄內容 |
NOOP | 無動作,除了來自服務器上的承認 |
PASS
|
系統登錄密碼 |
PASV | 請求服務器等待數據連接 |
PORT | IP 地址和兩字節的端口 ID |
PWD | 顯示當前工作目錄 |
QUIT | 從 FTP 服務器上退出登錄 |
REIN | 重新初始化登錄狀態連接 |
REST
|
由特定偏移量重啟文件傳遞 |
RETR
|
從服務器上找回(復制)文件 |
RMD
|
在服務器上刪除指定目錄 |
RNFR
|
對舊路徑重命名 |
RNTO
|
對新路徑重命名 |
SITE
|
由服務器提供的站點特殊參數 |
SMNT
|
掛載指定文件結構 |
STAT
|
在當前程序或目錄上返回信息 |
STOR
|
儲存(復制)文件到服務器上 |
STOU
|
儲存文件到服務器名稱上 |
STRU
|
數據結構(F=文件,R=記錄,P=頁面) |
SYST | 返回服務器使用的操作系統 |
TYPE | 數據類型(A=ASCII,E=EBCDIC,I=binary) |
USER
|
系統登錄的用戶名 |
FTP響應碼:
響應代碼 | 解釋說明 |
---|---|
110 | 新文件指示器上的重啟標記 |
120 | 服務器准備就緒的時間(分鍾數) |
125 | 打開數據連接,開始傳輸 |
150 | 打開連接 |
200 | 成功 |
202 | 命令沒有執行 |
211 | 系統狀態回復 |
212 | 目錄狀態回復 |
213 | 文件狀態回復 |
214 | 幫助信息回復 |
215 | 系統類型回復 |
220 | 服務就緒 |
221 | 退出網絡 |
225 | 打開數據連接 |
226 | 結束數據連接 |
227 | 進入被動模式(IP 地址、ID 端口) |
230 | 登錄因特網 |
250 | 文件行為完成 |
257 | 路徑名建立 |
331 | 要求密碼 |
332 | 要求帳號 |
350 | 文件行為暫停 |
421 | 服務關閉 |
425 | 無法打開數據連接 |
426 | 結束連接 |
450 | 文件不可用 |
451 | 遇到本地錯誤 |
452 | 磁盤空間不足 |
500 | 無效命令 |
501 | 錯誤參數 |
502 | 命令沒有執行 |
503 | 錯誤指令序列 |
504 | 無效命令參數 |
530 | 未登錄網絡 |
532 | 存儲文件需要帳號 |
550 | 文件不可用 |
551 | 不知道的頁類型 |
552 | 超過存儲分配 |
553 | 文件名不允許 |
實際使用例子
int FTP_Updata_Check(tFTP_DATA *pFtpData_cmd, tFTP_DATA *pFtpData_data)
{
int sock_ftp_cmd, sock_ftp_data;
struct sockaddr_in ftp_cmd, ftp_data;
uint32_t version_num = 0;
memset(pFtpData_data, 0, sizeof(tFTP_DATA));
memset(pFtpData_cmd, 0, sizeof(tFTP_DATA));
if ((sock_ftp_cmd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("FTP: Socket_cmd application failed. . .");
return -1;
}
ftp_cmd.sin_family = AF_INET;
ftp_cmd.sin_port = htons(FTP_PORT_IND);
ftp_cmd.sin_addr.s_addr = inet_addr(FTP_IP_ADDR);
USER_INFO(ePRINTF_LV2, "FTP: Connect Server IP:%s:%d", FTP_IP_ADDR, FTP_PORT_IND);
if (connect(sock_ftp_cmd, (struct sockaddr *)&ftp_cmd, sizeof (ftp_cmd)) < 0)
{
printf("FTP: The server connection failed. . .");
closesocket(sock_ftp_cmd);
return -1;
}
read(sock_ftp_cmd, pFtpData_cmd->recevice_buf, sizeof(pFtpData_cmd->recevice_buf) - 1);
sprintf(pFtpData_cmd->send_buf, "USER %s\r\n", FTP_USERNAME);
write(sock_ftp_cmd, pFtpData_cmd->send_buf, strlen(pFtpData_cmd->send_buf));
read(sock_ftp_cmd, pFtpData_cmd->recevice_buf, sizeof(pFtpData_cmd->recevice_buf) - 1);
sprintf( pFtpData_cmd->send_buf, "PASS %s\r\n", FTP_PASS);
write(sock_ftp_cmd, pFtpData_cmd->send_buf, strlen(pFtpData_cmd->send_buf));
read(sock_ftp_cmd, pFtpData_cmd->recevice_buf, sizeof(pFtpData_cmd->recevice_buf) - 1);
sprintf( pFtpData_cmd->send_buf, "PASV\r\n");
write(sock_ftp_cmd, pFtpData_cmd->send_buf, strlen(pFtpData_cmd->send_buf));
read(sock_ftp_cmd, pFtpData_cmd->recevice_buf, sizeof(pFtpData_cmd->recevice_buf) - 1);
pFtpData_data->port = ftp_get_port(pFtpData_cmd->recevice_buf);
if ((sock_ftp_data = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("FTP: Socket_dat application failed. . .");
closesocket(sock_ftp_cmd);
return -1;
}
ftp_data.sin_family = AF_INET;
ftp_data.sin_port = htons(pFtpData_data->port);
ftp_data.sin_addr.s_addr = inet_addr(FTP_IP_ADDR);
if (connect(sock_ftp_data, (struct sockaddr *)&ftp_data, sizeof (ftp_data)) < 0)
{
printf("FTP: The server connection failed. . .");
closesocket(sock_ftp_data);
closesocket(sock_ftp_cmd);
return -1;
}
sprintf(pFtpData_cmd->send_buf, "SIZE abc.text\r\n");
write(sock_ftp_cmd, pFtpData_cmd->send_buf, strlen(pFtpData_cmd->send_buf));
memset(pFtpData_cmd->recevice_buf, 0, sizeof(pFtpData_cmd->recevice_buf));
read(sock_ftp_cmd, pFtpData_cmd->recevice_buf, sizeof(pFtpData_cmd->recevice_buf) - 1);
USER_INFO(ePRINTF_LV3, "FTP: <<<<%s", pFtpData_cmd->recevice_buf);
if(strstr(pFtpData_cmd->recevice_buf, "File not found"))
{
printf("FTP: There is no file. return");
closesocket(sock_ftp_data);
closesocket(sock_ftp_cmd);
return 0;
}
sprintf(pFtpData_cmd->send_buf, "RETR abc.text\r\n");
write(sock_ftp_cmd, pFtpData_cmd->send_buf, strlen(pFtpData_cmd->send_buf));
memset(pFtpData_cmd->recevice_buf, 0, sizeof(pFtpData_cmd->recevice_buf));
read(sock_ftp_cmd, pFtpData_cmd->recevice_buf, sizeof(pFtpData_cmd->recevice_buf) - 1);
if(strstr(pFtpData_cmd->recevice_buf, "File not found"))
{
printf("FTP: There is no file. return");
closesocket(sock_ftp_data);
closesocket(sock_ftp_cmd);
return 0;
}
read(sock_ftp_data, pFtpData_data->recevice_buf, sizeof(pFtpData_data->recevice_buf) - 1);//讀文件內容
closesocket(sock_ftp_data);
closesocket(sock_ftp_cmd);
return 1;
}