freecplus框架-ftp客戶端

一、源代碼說明

freecplus是一個Linux系統下的C/C++開源框架,源代碼請前往C語言技術網(www.freecplus.net)下載。

本文介紹的是freecplus框架的ftp客戶端Cftp類。

Cftp類的聲明文件是freecplus/_ftp.h。

Cftp類的定義文件是freecplus/_ftp.cpp。

示例程序位於freecplus/demo目錄中。

編譯規則文件是freecplus/demo/makefile。

Cftp類是在ftplib開源庫的基礎之上做了二次封裝,ftplib開源庫的頭文件是freecplus/ftplib.h,函數定義文件是freecplus/ftplib.c。

ftplib是C代碼,用gcc先編譯成lib庫文件後,再用g++和_ftp.cpp以及目標文件一起編譯。

二、概述

本文不會介紹ftp協議的基礎知識和ftp命令,在閱讀本文之前,您必須熟悉ftp協議和命令才能看懂本文的內容。

三、Cftp類

類的聲明:

class Cftp
{
public:
  netbuf *m_ftpconn;   // ftp連接句柄。
  unsigned int m_size; // 文件的大小,單位:字節。
  char m_mtime[21];    // 文件的修改時間,格式:yyyymmddhh24miss。

  // 以下三個成員變量用於存放login方法登錄失敗的原因。
  bool m_connectfailed;    // 連接失敗。
  bool m_loginfailed;      // 登錄失敗,用戶名和密碼不正確,或沒有登錄權限。
  bool m_optionfailed;     // 設置傳輸模式失敗。

  Cftp();  // 類的構造函數。
 ~Cftp();  // 類的析構函數。

  void initdata();   // 初始化m_size和m_mtime成員變量。

  // 登錄ftp服務器。
  // host:ftp服務器ip地址和端口,中間用":"分隔,如"192.168.1.1:21"。
  // username:登錄ftp服務器用戶名。
  // password:登錄ftp服務器的密碼。
  // imode:傳輸模式,FTPLIB_PASSIVE是被動模式,FTPLIB_PORT是主動模式,缺省是被動模式。
  bool login(const char *host,const char *username,const char *password,const int imode=FTPLIB_PASSIVE);

  // 註銷。
  bool logout();

  // 獲取ftp服務器上文件的時間。
  // remotefilename:待獲取的文件名。
  // 返回值:false-失敗;true-成功,獲取到的文件時間存放在m_mtime成員變量中。
  bool mtime(const char *remotefilename);

  // 獲取ftp服務器上文件的大小。
  // remotefilename:待獲取的文件名。
  // 返回值:false-失敗;true-成功,獲取到的文件大小存放在m_size成員變量中。
  bool size(const char *remotefilename);

  // 改變ftp服務器的當前工作目錄。
  // remotedir:ftp服務器上的目錄名。
  // 返回值:true-成功;false-失敗。
  bool chdir(const char *remotedir);

  // 在ftp服務器上創建目錄。
  // remotedir:ftp服務器上待創建的目錄名。
  // 返回值:true-成功;false-失敗。
  bool mkdir(const char *remotedir);

  // 刪除ftp服務器上的目錄。
  // remotedir:ftp服務器上待刪除的目錄名。
  // 返回值:true-成功;false-失敗。
  bool rmdir(const char *remotedir);

  // 發送NLST命令列出ftp服務器的目錄和文件名。
  // remotedir:ftp服務器的目錄名。
  // listfilename:用於保存從服務器返回的目錄和文件名列表。
  // 返回值:true-成功;false-失敗。
  // 注意:如果列出的是ftp服務器當前目錄,remotedir用"","*","."都可以,但是,不規範的ftp服務器可能有差別。
  bool nlist(const char *remotedir,const char *listfilename);

  // 從ftp服務器上獲取文件。
  // remotefilename:待獲取ftp服務器上的文件名。
  // localfilename:保存到本地的文件名。
  // bCheckMTime:文件傳輸完成後,是否覈對遠程文件傳輸前後的時間,保證文件的完整性。
  // 返回值:true-成功;false-失敗。
  // 注意:文件在傳輸的過程中,採用臨時文件命名的方法,即在localfilename後加".tmp",在傳輸
  // 完成後才正式改爲localfilename。
  bool get(const char *remotefilename,const char *localfilename,const bool bCheckMTime=true);

  // 向ftp服務器發送文件。
  // localfilename:本地待發送的文件名。
  // remotefilename:發送到ftp服務器上的文件名。
  // bCheckSize:文件傳輸完成後,是否覈對本地文件和遠程文件的大小,保證文件的完整性。
  // 返回值:true-成功;false-失敗。
  // 注意:文件在傳輸的過程中,採用臨時文件命名的方法,即在remotefilename後加".tmp",在傳輸
  // 完成後才正式改爲remotefilename。
  bool put(const char *localfilename,const char *remotefilename,const bool bCheckSize=true);

  // 刪除ftp服務器上的文件。
  // remotefilename:待刪除的ftp服務器上的文件名。
  // 返回值:true-成功;false-失敗。
  bool ftpdelete(const char *remotefilename);

  // 重命名ftp服務器上的文件。
  // srcremotefilename:ftp服務器上的原文件名。
  // dstremotefilename:ftp服務器上的目標文件名。
  // 返回值:true-成功;false-失敗。
  bool ftprename(const char *srcremotefilename,const char *dstremotefilename);

  /* 以下三個方法如果理解不了就算了,可以不啓用。 */
  // 發送LIST命令列出ftp服務器目錄中的文件。
  // 參數和返回值與nlist方法相同。
  bool dir(const char *remotedir,const char *listfilename);

  // 向ftp服務器發送site命令。
  // command:命令的內容。
  // 返回值:true-成功;false-失敗。
  bool site(const char *command);

  // 獲取服務器返回信息的最後一條(return a pointer to the last response received)。
  char *response();
};

四、準備測試環境

在演示示例程序之前,我認爲您已經是一個職業的C/C++程序員,熟悉Linux操作系統、熟悉ftp協議。

1、創建Linux操作系統用戶

創建freecplus用戶,用戶組爲bin,用戶根目錄爲/home/freecplus,密碼爲freecpluspwd

在這裏插入圖片描述
2、安裝配置ftp服務器

具體操作請參考C語言技術網(www.freecplus.net)的相關文章,或在網上搜索相關的文章。

3、配置防火牆

具體操作請參考C語言技術網(www.freecplus.net)的相關文章,或在網上搜索相關的文章。

4、準備測試的文件

把freecplus框架的源代碼複製到/home/freecplus目錄,如下:

在這裏插入圖片描述

五、示例程序

1、獲取服務器文件列表、時間和大小

示例(demo50.cpp)

/*
 *  程序名:demo50.cpp,此程序演示採用freecplus框架的Cftp類獲取服務器文件列表、時間和大小。
 *  作者:C語言技術網(www.freecplus.net) 日期:20190525
*/
#include "../_ftp.h"

int main(int argc,char *argv[])
{
  Cftp ftp;

  // 登錄遠程FTP服務器,請改爲您自己服務器的ip地址。
  if (ftp.login("172.16.0.15:21","freecplus","freecpluspwd",FTPLIB_PASSIVE) == false)
  {
    printf("ftp.login(172.16.0.15:21(freecplus/freecpluspwd)) failed.\n"); return -1;
  }

  // 獲取服務器上/home/freecplus/*.h文件列表,保存在本地的/tmp/list/tmp.list文件中。
  // 如果/tmp/list目錄不存在,就創建它。
  if (ftp.nlist("/home/freecplus/*.h","/tmp/list/tmp.list")==false) 
  { printf("ftp.nlist() failed.\n"); return -1; }

  CFile File;    // 採用freecplus框架的CFile類來操作list文件。
  char strFileName[301];

  File.Open("/tmp/list/tmp.list","r");  // 打開list文件。

  while(true)    // 獲取每個文件的時間和大小。
  {
    if (File.Fgets(strFileName,300,true)==false) break;

    ftp.mtime(strFileName); // 獲取文件時間。
    ftp.size(strFileName);  // 獲取文件大小。

    printf("filename=%s,mtime=%s,size=%d\n",strFileName,ftp.m_mtime,ftp.m_size);   
  }
}

運行效果

在這裏插入圖片描述

2、把文件上傳到服務器

示例(demo51.cpp)

/*
 *  程序名:demo51.cpp,此程序演示採用freecplus框架的Cftp類上傳文件。
 *  作者:C語言技術網(www.freecplus.net) 日期:20190525
*/
#include "../_ftp.h"

int main(int argc,char *argv[])
{
  Cftp ftp;

  // 登錄遠程FTP服務器,請改爲您自己服務器的ip地址。
  if (ftp.login("172.16.0.15:21","freecplus","freecpluspwd",FTPLIB_PASSIVE) == false)
  {
    printf("ftp.login(172.16.0.15:21(freecplus/freecpluspwd)) failed.\n"); return -1;
  }

  // 在ftp服務器上創建/home/freecplus/tmp,注意,如果目錄已存在,會返回失敗。
  if (ftp.mkdir("/home/freecplus/tmp")==false) { printf("ftp.mkdir() failed.\n"); return -1; }

  // 把ftp服務器上的工作目錄切換到/home/freecplus/tmp
  if (ftp.chdir("/home/freecplus/tmp")==false) { printf("ftp.chdir() failed.\n"); return -1; }

  // 把本地的demo51.cpp上傳到ftp服務器的當前工作目錄。
  ftp.put("demo51.cpp","demo51.cpp");

  // 如果不調用chdir切換工作目錄,以下代碼也可以直接上傳文件。
  // ftp.put("demo51.cpp","/home/freecplus/tmp/demo51.cpp");

  printf("put demo51.cpp ok.\n");  
}

3、從服務器下載文件

示例(demo52.cpp)

/*
 *  程序名:demo52.cpp,此程序演示採用freecplus框架的Cftp類下載文件。
 *  作者:C語言技術網(www.freecplus.net) 日期:20190525
*/
#include "../_ftp.h"

int main(int argc,char *argv[])
{
  Cftp ftp;

  // 登錄遠程FTP服務器,請改爲您自己服務器的ip地址。
  if (ftp.login("172.16.0.15:21","freecplus","freecpluspwd",FTPLIB_PASSIVE) == false)
  {
    printf("ftp.login(172.16.0.15:21(freecplus/freecpluspwd)) failed.\n"); return -1;
  }

  // 把服務器上的/home/freecplus/tmp/demo51.cpp下載到本地,存爲/tmp/test/demo51.cpp。
  // 如果本地的/tmp/test目錄不存在,就創建它。
  if (ftp.get("/home/freecplus/tmp/demo51.cpp","/tmp/test/demo51.cpp")==false)
  { printf("ftp.get() failed.\n"); return -1; }

  printf("get /home/freecplus/tmp/demo51.cpp ok.\n");  

  // 刪除服務上的/home/freecplus/tmp/demo51.cpp文件。
  if (ftp.ftpdelete("/home/freecplus/tmp/demo51.cpp")==false) 
  { printf("ftp.ftpdelete() failed.\n"); return -1; }

  printf("delete /home/freecplus/tmp/demo51.cpp ok.\n");  

  // 刪除服務器上的/home/freecplus/tmp目錄,如果目錄非空,刪除將失敗。
  if (ftp.rmdir("/home/freecplus/tmp")==false) { printf("ftp.rmdir() failed.\n");return -1; }
}

六、版權聲明

C語言技術網原創文章,轉載請說明文章的來源、作者和原文的鏈接。
來源:C語言技術網(www.freecplus.net)
作者:碼農有道

如果這篇文章對您有幫助,請點贊支持,或在您的博客中轉發我的文章,謝謝!!!
如果文章有錯別字,或者內容有錯誤,或其他的建議和意見,請您留言指正,非常感謝!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章