C++实现ftp客户端

来源:互联网 发布:数字图像处理算法研究 编辑:程序博客网 时间:2024/05/01 03:44
c++commandstringapisocketdownload
[cpp] view plaincopyprint?
  1. #ifndef CLIENT_H_  
  2. #define CLIENT_H_  
  3.   
  4. #include <sys/socket.h>  
  5. #include <unistd.h>  
  6. #include <fcntl.h>  
  7. #include <stdio.h>  
  8. #include <stdlib.h>  
  9. #include <sys/types.h>  
  10. #include <sys/ioctl.h>  
  11. #include <netinet/in.h>  
  12. #include <sys/stat.h>  
  13. #include <netdb.h>  
  14. #include <errno.h>  
  15. #include <arpa/inet.h>  
  16. #include <sys/stat.h>  
  17. #include <string>  
  18. #include <list>  
  19.   
  20.   
  21. #define INVALID_SOCKET              -1  
  22. #define FTP_API                     int  
  23. #define MAX_PATH                    260  
  24. #define trace                       printf  
  25.   
  26. #define FTP_PARAM_BASE  
  27. #define FTP_DEFAULT_PORT            "21"                            //FTP默认端口号  
  28. #define FTP_DEFAULT_BUFFER          1024*4                          //FTP下载缓冲默认大小  
  29. #define FTP_DEFAULT_PATH            "/mnt/dvs/"                     //FTP默认保存路径  
  30.       
  31. #define FTP_COMMAND_BASE            1000  
  32. #define FTP_COMMAND_END             FTP_COMMAND_BASE + 30  
  33. #define FTP_COMMAND_USERNAME        FTP_COMMAND_BASE + 1            //用户名  
  34. #define FTP_COMMAND_PASSWORD        FTP_COMMAND_BASE + 2            //密码  
  35. #define FTP_COMMAND_QUIT            FTP_COMMAND_BASE + 3            //退出  
  36. #define FTP_COMMAND_CURRENT_PATH    FTP_COMMAND_BASE + 4            // 获取文件路径  
  37. #define FTP_COMMAND_TYPE_MODE       FTP_COMMAND_BASE + 5            // 改变传输模式  
  38. #define FTP_COMMAND_PSAV_MODE       FTP_COMMAND_BASE + 6            // 被动端口模式  
  39. #define FTP_COMMAND_DIR             FTP_COMMAND_BASE + 7            // 获取文件列表  
  40. #define FTP_COMMAND_CHANGE_DIRECTORY FTP_COMMAND_BASE + 8           // 改变路径  
  41. #define FTP_COMMAND_DELETE_FILE     FTP_COMMAND_BASE + 9            // 删除文件  
  42. #define FTP_COMMAND_DELETE_DIRECTORY FTP_COMMAND_BASE + 10          // 删除目录/文件夹  
  43. #define FTP_COMMAND_CREATE_DIRECTORY FTP_COMMAND_BASE + 11          // 创建目录/文件夹  
  44. #define FTP_COMMAND_RENAME_BEGIN    FTP_COMMAND_BASE  +12           // 开始重命名  
  45. #define FTP_COMMAND_RENAME_END      FTP_COMMAND_BASE + 13           // 重命名结束  
  46. #define FTP_COMMAND_FILE_SIZE       FTP_COMMAND_BASE + 14           // 获取文件大小  
  47. #define FTP_COMMAND_DOWNLOAD_POS    FTP_COMMAND_BASE + 15           // 下载文件从指定位置开始  
  48. #define FTP_COMMAND_DOWNLOAD_FILE   FTP_COMMAND_BASE + 16           // 下载文件  
  49. #define FTP_COMMAND_UPLOAD_FILE     FTP_COMMAND_BASE + 17           // 上传文件  
  50. #define FTP_COMMAND_APPEND_FILE     FTP_COMMAND_BASE + 18           // 追加上载文件     
  51.   
  52. /*        登陆步骤 
  53.         login2Server 
  54.             | 
  55.         inputUserName 
  56.             | 
  57.         inputPassWord 
  58.             | 
  59.           具体操作 
  60.             | 
  61.           quit 
  62. */  
  63.   
  64. class CFTPManager   
  65. {  
  66. public :  
  67.       
  68.     enum type {  
  69.         binary = 0x31,  
  70.         ascii,  
  71.     };  
  72.       
  73.     CFTPManager(void);  
  74.   
  75.     virtual ~CFTPManager(void);  
  76.       
  77.     // ! 登陆服务器  
  78.     FTP_API login2Server(const std::string &serverIP);  
  79.   
  80.     // !输入用户名  
  81.     FTP_API inputUserName(const std::string &userName);  
  82.   
  83.     // !输入密码  
  84.     FTP_API inputPassWord(const std::string &password);  
  85.   
  86.     // !退出FTP  
  87.     FTP_API quitServer(void);  
  88.   
  89.     // !命令: PWD  
  90.     const std::string PWD();  
  91.   
  92.     // !设置传输格式 2进制  还是ascii方式传输  
  93.     FTP_API setTransferMode(type mode);  
  94.   
  95.     // !设置为被动模式  
  96.     const std::string Pasv();  
  97.   
  98.     // ! 命令: DIR  
  99.     const std::string Dir(const std::string &path);  
  100.   
  101.     // !命令 : CD  
  102.     FTP_API CD(const std::string &path);  
  103.   
  104.     // !删除文件  
  105.     FTP_API DeleteFile(const std::string &strRemoteFile);  
  106.   
  107.     // ! 删除文件夹/目录  
  108.     FTP_API DeleteDirectory(const std::string &strRemoteDir);  
  109.   
  110.     // ! 创建目录/文件夹  
  111.     FTP_API CreateDirectory(const std::string &strRemoteDir);  
  112.   
  113.     // !重命名  
  114.     FTP_API Rename(const std::string &strRemoteFile, const std::string &strNewFile);  
  115.   
  116.     // !获取文件大小  
  117.     long getFileLength(const std::string &strRemoteFile);  
  118.   
  119.     // !关闭连接  
  120.     void Close(int sock);  
  121.   
  122.     // 下载文件  
  123.     FTP_API Get(const std::string &strRemoteFile, const std::string &strLocalFile);  
  124.   
  125.     // 上载文件  支持断电传送方式  
  126.     FTP_API Put(const std::string &strRemoteFile, const std::string &strLocalFile);  
  127.   
  128.   
  129. private:  
  130.     // !合成发送到服务器的命令  
  131.     const std::string parseCommand(const unsigned int command, const std::string &strParam);  
  132.   
  133.     // ! 建立连接  
  134.     FTP_API Connect(int socketfd, const std::string &serverIP, unsigned int nPort);  
  135.   
  136.     // ! 返回服务器信息  
  137.     const std::string serverResponse(int sockfd);  
  138.   
  139.     // !获取服务器数据  
  140.     FTP_API getData(int fd, char *strBuf, unsigned long length);  
  141.   
  142.     // !发送命令  
  143.     FTP_API Send(int fd, const std::string &cmd);  
  144.   
  145.     // !发送命令  
  146.     FTP_API Send(int fd, const char *cmd, const size_t len);  
  147.   
  148.     // !建立数据连接  
  149.     FTP_API createDataLink(int data_fd);  
  150.   
  151.     // !解析PASV模式返回的字符串获取FTP端口号和FTP服务器IP  
  152.     FTP_API ParseString(std::list<std::string> strArray, unsigned long & nPort ,std::string & strServerIp);  
  153.   
  154.     // 打开本地文件  
  155.     FILE *createLocalFile(const std::string &strLocalFile);  
  156.   
  157.     // 下载文件   
  158.     FTP_API downLoad(const std::string &strRemoteFile, const std::string &strLocalFile, const int pos = 0, const unsigned int length = 0);  
  159.   
  160.     // 解析返回ftp命令的值  
  161.     FTP_API parseResponse(const std::string &str);  
  162.   
  163. private:  
  164.     //!控制连接套接字  
  165.     int     m_cmdSocket;  
  166.       
  167.     // !当前用户名  
  168.     std::string m_strUserName;  
  169.   
  170.     // !当前用户密码  
  171.     std::string m_strPassWord;  
  172.   
  173.     // !服务器的IP  
  174.     std::string m_strServerIP;  
  175.   
  176.     // !服务器Port  
  177.     unsigned int m_nServerPort;  
  178.   
  179.     // !服务器回应信息缓存  
  180.     std::string m_strResponse;  
  181.   
  182.     // !保存命令参数  
  183.     std::string m_commandStr;  
  184.   
  185.     // !当前使用的命令参数  
  186.     unsigned int m_nCurrentCommand;  
  187.   
  188.     // !是否登陆标志。  
  189.     bool    m_bLogin;  
  190. };  
  191.   
  192.   
  193. #endif  


[cpp] view plaincopyprint?
  1. #include "../Source/FTPManager.h"  
  2.   
  3. static int SplitString( std::string strSrc, std::list<std::string> &strArray , std::string strFlag)  
  4. {  
  5.     int pos = 1;   
  6.   
  7.     while((pos = (int)strSrc.find_first_of(strFlag.c_str())) > 0)   
  8.     {  
  9.         strArray.insert(strArray.end(), strSrc.substr(0 , pos));  
  10.         strSrc = strSrc.substr(pos + 1, strSrc.length() - pos - 1);   
  11.     }  
  12.   
  13.     strArray.insert(strArray.end(), strSrc.substr(0, strSrc.length()));  
  14.   
  15.     return 0;   
  16. }  
  17.   
  18. CFTPManager::CFTPManager(void): m_bLogin(false)  
  19. {  
  20.     m_cmdSocket = socket(AF_INET, SOCK_STREAM, 0);  
  21.       
  22. }  
  23.   
  24. CFTPManager::~CFTPManager(void)  
  25. {  
  26.     std::string strCmdLine = parseCommand(FTP_COMMAND_QUIT, "");  
  27.   
  28.     Send(m_cmdSocket, strCmdLine.c_str());  
  29.     close(m_cmdSocket);  
  30.     m_bLogin = false;  
  31. }  
  32.   
  33. FTP_API CFTPManager::login2Server(const std::string &serverIP)  
  34. {  
  35.     std::string strPort;  
  36.     int pos = serverIP.find_first_of(":");  
  37.   
  38.     if (pos > 0)  
  39.     {  
  40.         strPort = serverIP.substr(pos + 1, serverIP.length() - pos);  
  41.     }  
  42.     else  
  43.     {  
  44.         pos = serverIP.length();  
  45.         strPort = FTP_DEFAULT_PORT;  
  46.     }  
  47.   
  48.     m_strServerIP = serverIP.substr(0, pos);  
  49.     m_nServerPort = atol(strPort.c_str());  
  50.   
  51.     trace("IP: %s port: %d\n", m_strServerIP.c_str(), m_nServerPort);  
  52.   
  53.     if (Connect(m_cmdSocket, m_strServerIP, m_nServerPort) < 0)  
  54.     {  
  55.           
  56.         return -1;  
  57.     }  
  58.       
  59.     m_strResponse = serverResponse(m_cmdSocket);  
  60.     printf("@@@@Response: %s", m_strResponse.c_str());  
  61.   
  62.     return  parseResponse(m_strResponse);  
  63. }  
  64.   
  65. FTP_API CFTPManager::inputUserName(const std::string &userName)  
  66. {  
  67.     std::string strCommandLine = parseCommand(FTP_COMMAND_USERNAME, userName);  
  68.   
  69.     m_strUserName = userName;  
  70.   
  71.     if (Send(m_cmdSocket, strCommandLine) < 0)  
  72.     {  
  73.         return -1;  
  74.     }  
  75.   
  76.     m_strResponse = serverResponse(m_cmdSocket);  
  77.     printf("Response: %s\n", m_strResponse.c_str());  
  78.   
  79.     return parseResponse(m_strResponse);  
  80. }  
  81.   
  82. FTP_API CFTPManager::inputPassWord(const std::string &password)  
  83. {  
  84.     std::string strCmdLine = parseCommand(FTP_COMMAND_PASSWORD, password);  
  85.   
  86.     m_strPassWord = password;  
  87.     if (Send(m_cmdSocket, strCmdLine) < 0)  
  88.     {  
  89.         return -1;  
  90.     }  
  91.     else  
  92.     {  
  93.         m_bLogin = true;  
  94.   
  95.         m_strResponse = serverResponse(m_cmdSocket);  
  96.         printf("Response: %s\n", m_strResponse.c_str());  
  97.   
  98.         return parseResponse(m_strResponse);  
  99.     }  
  100. }  
  101.   
  102. FTP_API CFTPManager::quitServer(void)  
  103. {  
  104.     std::string strCmdLine = parseCommand(FTP_COMMAND_QUIT, "");  
  105.     if (Send(m_cmdSocket, strCmdLine) < 0)  
  106.     {  
  107.         return -1;  
  108.     }  
  109.     else  
  110.     {  
  111.         m_strResponse = serverResponse(m_cmdSocket);  
  112.         printf("Response: %s\n", m_strResponse.c_str());  
  113.   
  114.         return parseResponse(m_strResponse);  
  115.     }  
  116.   
  117. }  
  118.   
  119. const std::string CFTPManager::PWD()  
  120. {  
  121.     std::string strCmdLine = parseCommand(FTP_COMMAND_CURRENT_PATH, "");  
  122.   
  123.     if (Send(m_cmdSocket, strCmdLine.c_str()) < 0)  
  124.     {  
  125.         return "";  
  126.     }  
  127.     else  
  128.     {  
  129.         return serverResponse(m_cmdSocket);  
  130.     }  
  131. }  
  132.   
  133.   
  134. FTP_API CFTPManager::setTransferMode(type mode)  
  135. {  
  136.     std::string strCmdLine;  
  137.   
  138.     switch (mode)  
  139.     {  
  140.     case binary:  
  141.         strCmdLine = parseCommand(FTP_COMMAND_TYPE_MODE, "I");  
  142.         break;  
  143.     case ascii:  
  144.         strCmdLine = parseCommand(FTP_COMMAND_TYPE_MODE, "A");  
  145.         break;  
  146.     default:  
  147.         break;  
  148.     }  
  149.   
  150.     if (Send(m_cmdSocket, strCmdLine.c_str()) < 0)  
  151.     {  
  152.         assert(false);  
  153.     }  
  154.     else  
  155.     {     
  156.         m_strResponse  = serverResponse(m_cmdSocket);  
  157.         printf("@@@@Response: %s", m_strResponse.c_str());  
  158.   
  159.         return parseResponse(m_strResponse);  
  160.     }  
  161. }  
  162.   
  163.   
  164. const std::string CFTPManager::Pasv()  
  165. {  
  166.     std::string strCmdLine = parseCommand(FTP_COMMAND_PSAV_MODE, "");  
  167.   
  168.     if (Send(m_cmdSocket, strCmdLine.c_str()) < 0)  
  169.     {  
  170.         return "";  
  171.     }  
  172.     else  
  173.     {  
  174.         m_strResponse = serverResponse(m_cmdSocket);  
  175.   
  176.         return m_strResponse;  
  177.     }  
  178. }  
  179.   
  180.   
  181. const std::string CFTPManager::Dir(const std::string &path)  
  182. {  
  183.     int dataSocket = socket(AF_INET, SOCK_STREAM, 0);  
  184.   
  185.     if (createDataLink(dataSocket) < 0)  
  186.     {  
  187.         return "";  
  188.     }  
  189.     // 数据连接成功  
  190.     std::string strCmdLine = parseCommand(FTP_COMMAND_DIR, path);  
  191.   
  192.     if (Send(m_cmdSocket, strCmdLine) < 0)  
  193.     {  
  194.         trace("@@@@Response: %s\n", serverResponse(m_cmdSocket).c_str());  
  195.         close(dataSocket);  
  196.         return "";  
  197.     }  
  198.     else  
  199.     {  
  200.         trace("@@@@Response: %s\n", serverResponse(m_cmdSocket).c_str());  
  201.         m_strResponse = serverResponse(dataSocket);  
  202.   
  203.         trace("@@@@Response: \n%s\n", m_strResponse.c_str());  
  204.         close(dataSocket);  
  205.   
  206.         return m_strResponse;  
  207.     }  
  208.       
  209. }  
  210.   
  211.   
  212. FTP_API CFTPManager::CD(const std::string &path)  
  213. {  
  214.     assert(m_cmdSocket != INVALID_SOCKET);  
  215.   
  216.     std::string strCmdLine = parseCommand(FTP_COMMAND_CHANGE_DIRECTORY, path);  
  217.   
  218.     if (Send(m_cmdSocket, strCmdLine) < 0)  
  219.     {  
  220.         return -1;  
  221.     }  
  222.           
  223.     m_strResponse = serverResponse(m_cmdSocket);  
  224.       
  225.     trace("@@@@Response: %s\n", m_strResponse.c_str());  
  226.     return parseResponse(m_strResponse);  
  227. }  
  228.   
  229. FTP_API CFTPManager::DeleteFile(const std::string &strRemoteFile)  
  230. {  
  231.     assert(m_cmdSocket != INVALID_SOCKET);  
  232.   
  233.     std::string strCmdLine = parseCommand(FTP_COMMAND_DELETE_FILE, strRemoteFile);  
  234.   
  235.     if (Send(m_cmdSocket, strCmdLine) < 0)  
  236.     {  
  237.         return -1;  
  238.     }  
  239.   
  240.     m_strResponse = serverResponse(m_cmdSocket);  
  241.     printf("@@@@Response: %s\n", m_strResponse.c_str());  
  242.     return parseResponse(m_strResponse);  
  243. }  
  244.   
  245. FTP_API CFTPManager::DeleteDirectory(const std::string &strRemoteDir)  
  246. {  
  247.     assert(m_cmdSocket != INVALID_SOCKET);  
  248.   
  249.     std::string strCmdLine = parseCommand(FTP_COMMAND_DELETE_DIRECTORY, strRemoteDir);  
  250.   
  251.     if (Send(m_cmdSocket, strCmdLine) < 0)  
  252.     {  
  253.         return -1;  
  254.     }  
  255.       
  256.     m_strResponse = serverResponse(m_cmdSocket);  
  257.   
  258.     trace("@@@@Response: %s\n", m_strResponse.c_str());  
  259.     return parseResponse(m_strResponse);  
  260. }  
  261.   
  262. FTP_API CFTPManager::CreateDirectory(const std::string &strRemoteDir)  
  263. {  
  264.     assert(m_cmdSocket != INVALID_SOCKET);  
  265.   
  266.     std::string strCmdLine = parseCommand(FTP_COMMAND_CREATE_DIRECTORY, strRemoteDir);  
  267.   
  268.     if (Send(m_cmdSocket, strCmdLine) < 0)  
  269.     {  
  270.         return -1;  
  271.     }  
  272.       
  273.     m_strResponse = serverResponse(m_cmdSocket);  
  274.   
  275.     trace("@@@@Response: %s\n", m_strResponse.c_str());  
  276.     return parseResponse(m_strResponse);  
  277. }  
  278.   
  279. FTP_API CFTPManager::Rename(const std::string &strRemoteFile, const std::string &strNewFile)  
  280. {  
  281.     assert(m_cmdSocket != INVALID_SOCKET);  
  282.   
  283.     std::string strCmdLine = parseCommand(FTP_COMMAND_RENAME_BEGIN, strRemoteFile);  
  284.     Send(m_cmdSocket, strCmdLine);  
  285.     trace("@@@@Response: %s\n", serverResponse(m_cmdSocket).c_str());  
  286.   
  287.     Send(m_cmdSocket, parseCommand(FTP_COMMAND_RENAME_END, strNewFile));  
  288.   
  289.     m_strResponse = serverResponse(m_cmdSocket);  
  290.     trace("@@@@Response: %s\n", m_strResponse.c_str());  
  291.     return parseResponse(m_strResponse);  
  292. }  
  293.   
  294. long CFTPManager::getFileLength(const std::string &strRemoteFile)  
  295. {  
  296.     assert(m_cmdSocket != INVALID_SOCKET);  
  297.   
  298.     std::string strCmdLine = parseCommand(FTP_COMMAND_FILE_SIZE, strRemoteFile);  
  299.   
  300.     if (Send(m_cmdSocket, strCmdLine) < 0)  
  301.     {  
  302.         return -1;  
  303.     }  
  304.   
  305.     m_strResponse = serverResponse(m_cmdSocket);  
  306.   
  307.     trace("@@@@Response: %s\n", m_strResponse.c_str());  
  308.   
  309.     std::string strData = m_strResponse.substr(0, 3);  
  310.     unsigned long val = atol(strData.c_str());  
  311.   
  312.     if (val == 213)  
  313.     {  
  314.         strData = m_strResponse.substr(4);  
  315.         trace("strData: %s\n", strData.c_str());  
  316.         val = atol(strData.c_str());  
  317.   
  318.         return val;  
  319.     }  
  320.   
  321.     return -1;  
  322. }  
  323.   
  324.   
  325. void CFTPManager::Close(int sock)  
  326. {  
  327.     shutdown(sock, SHUT_RDWR);  
  328.     close(sock);  
  329.     sock = INVALID_SOCKET;  
  330. }  
  331.   
  332. FTP_API CFTPManager::Get(const std::string &strRemoteFile, const std::string &strLocalFile)  
  333. {  
  334.     return downLoad(strRemoteFile, strLocalFile);  
  335. }  
  336.   
  337.   
  338. FTP_API CFTPManager::Put(const std::string &strRemoteFile, const std::string &strLocalFile)  
  339. {  
  340.     std::string strCmdLine;  
  341.     const unsigned long dataLen = FTP_DEFAULT_BUFFER;  
  342.     char strBuf[dataLen] = {0};  
  343.     unsigned long nSize = getFileLength(strRemoteFile);  
  344.     unsigned long nLen = 0;  
  345. //  struct stat sBuf;  
  346. //   
  347. //  assert(stat(strLocalFile.c_str(), &sBuf) == 0);  
  348. //  trace("size: %d\n", sBuf.st_size);  
  349.   
  350.     FILE *pFile = fopen(strLocalFile.c_str(), "rb");  // 以只读方式打开  且文件必须存在  
  351.     assert(pFile != NULL);  
  352.   
  353.     int data_fd = socket(AF_INET, SOCK_STREAM, 0);  
  354.     assert(data_fd != -1);  
  355.   
  356.     if (createDataLink(data_fd) < 0)  
  357.     {  
  358.         return -1;  
  359.     }  
  360.       
  361.     if (nSize == -1)  
  362.     {  
  363.         strCmdLine = parseCommand(FTP_COMMAND_UPLOAD_FILE, strRemoteFile);  
  364.     }  
  365.     else  
  366.     {  
  367.         strCmdLine = parseCommand(FTP_COMMAND_APPEND_FILE, strRemoteFile);  
  368.     }  
  369.   
  370.     if (Send(m_cmdSocket, strCmdLine) < 0)  
  371.     {  
  372.         Close(data_fd);  
  373.         return -1;  
  374.     }  
  375.   
  376.     trace("@@@@Response: %s\n", serverResponse(m_cmdSocket).c_str());  
  377.   
  378.     fseek(pFile, nSize, SEEK_SET);  
  379.     while (!feof(pFile))  
  380.     {  
  381.         nLen = fread(strBuf, 1, dataLen, pFile);  
  382.         if (nLen < 0)  
  383.         {  
  384.             break;  
  385.         }  
  386.   
  387.         if (Send(data_fd, strBuf) < 0)  
  388.         {  
  389.             Close(data_fd);  
  390.             return -1;  
  391.         }  
  392.     }  
  393.   
  394.     trace("@@@@Response: %s\n", serverResponse(data_fd).c_str());  
  395.   
  396.     Close(data_fd);  
  397.     trace("@@@@Response: %s\n", serverResponse(m_cmdSocket).c_str());  
  398.     fclose(pFile);  
  399.   
  400.     return 0;  
  401. }  
  402.   
  403. const std::string CFTPManager::parseCommand(const unsigned int command, const std::string &strParam)  
  404. {  
  405.     if (command < FTP_COMMAND_BASE || command > FTP_COMMAND_END)  
  406.     {  
  407.         return "";  
  408.     }  
  409.   
  410.     std::string strCommandLine;  
  411.   
  412.     m_nCurrentCommand = command;  
  413.     m_commandStr.clear();  
  414.   
  415.     switch (command)  
  416.     {  
  417.     case FTP_COMMAND_USERNAME:  
  418.         strCommandLine = "USER ";  
  419.         break;  
  420.     case FTP_COMMAND_PASSWORD:  
  421.         strCommandLine = "PASS ";  
  422.         break;  
  423.     case FTP_COMMAND_QUIT:  
  424.         strCommandLine = "QUIT ";  
  425.         break;  
  426.     case FTP_COMMAND_CURRENT_PATH:  
  427.         strCommandLine = "PWD ";  
  428.         break;  
  429.     case FTP_COMMAND_TYPE_MODE:  
  430.         strCommandLine = "TYPE ";  
  431.         break;  
  432.     case FTP_COMMAND_PSAV_MODE:  
  433.         strCommandLine = "PASV ";  
  434.         break;  
  435.     case FTP_COMMAND_DIR:  
  436.         strCommandLine = "LIST ";  
  437.         break;  
  438.     case FTP_COMMAND_CHANGE_DIRECTORY:  
  439.         strCommandLine = "CWD ";  
  440.         break;  
  441.     case FTP_COMMAND_DELETE_FILE:  
  442.         strCommandLine = "DELE ";  
  443.         break;  
  444.     case FTP_COMMAND_DELETE_DIRECTORY:  
  445.         strCommandLine = "RMD ";  
  446.         break;  
  447.     case FTP_COMMAND_CREATE_DIRECTORY:  
  448.         strCommandLine = "MKD ";  
  449.         break;  
  450.     case FTP_COMMAND_RENAME_BEGIN:  
  451.         strCommandLine = "RNFR ";  
  452.         break;  
  453.     case FTP_COMMAND_RENAME_END:  
  454.         strCommandLine = "RNTO ";  
  455.         break;  
  456.     case FTP_COMMAND_FILE_SIZE:  
  457.         strCommandLine = "SIZE ";  
  458.         break;  
  459.     case FTP_COMMAND_DOWNLOAD_FILE:  
  460.         strCommandLine = "RETR ";  
  461.         break;  
  462.     case FTP_COMMAND_DOWNLOAD_POS:  
  463.         strCommandLine = "REST ";  
  464.         break;  
  465.     case FTP_COMMAND_UPLOAD_FILE:  
  466.         strCommandLine = "STOR ";  
  467.         break;  
  468.     case FTP_COMMAND_APPEND_FILE:  
  469.         strCommandLine = "APPE ";  
  470.         break;  
  471.     default :  
  472.         break;  
  473.     }  
  474.   
  475.     strCommandLine += strParam;  
  476.     strCommandLine += "\r\n";  
  477.   
  478.     m_commandStr = strCommandLine;  
  479.     trace("parseCommand: %s\n", m_commandStr.c_str());  
  480.   
  481.     return m_commandStr;  
  482. }  
  483.   
  484. FTP_API CFTPManager::Connect(int socketfd, const std::string &serverIP, unsigned int nPort)  
  485. {  
  486.     if (socketfd == INVALID_SOCKET)  
  487.     {  
  488.         return -1;  
  489.     }  
  490.   
  491.     unsigned int argp = 1;  
  492.     int error = -1;  
  493.     int len = sizeof(int);  
  494.     struct sockaddr_in  addr;  
  495.     bool ret = false;  
  496.     timeval stime;  
  497.     fd_set  set;  
  498.   
  499.     ioctl(socketfd, FIONBIO, &argp);  //设置为非阻塞模式  
  500.   
  501.     memset(&addr, 0, sizeof(struct sockaddr_in));  
  502.     addr.sin_family = AF_INET;  
  503.     addr.sin_port   = htons(nPort);  
  504.     addr.sin_addr.s_addr = inet_addr(serverIP.c_str());  
  505.     bzero(&(addr.sin_zero), 8);  
  506.   
  507.     trace("Address: %s %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));  
  508.       
  509.     if (connect(socketfd, (struct sockaddr*)&addr, sizeof(struct sockaddr)) == -1)   //若直接返回 则说明正在进行TCP三次握手  
  510.     {  
  511.         stime.tv_sec = 20;  //设置为1秒超时  
  512.         stime.tv_usec = 0;  
  513.         FD_ZERO(&set);  
  514.         FD_SET(socketfd, &set);  
  515.   
  516.         if (select(socketfd + 1, NULL, &set, NULL, &stime) > 0)   ///在这边等待 阻塞 返回可以读的描述符 或者超时返回0  或者出错返回-1  
  517.         {  
  518.             getsockopt(socketfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t*)&len);  
  519.             if (error == 0)  
  520.             {  
  521.                 ret = true;  
  522.             }  
  523.             else  
  524.             {  
  525.                 ret = false;  
  526.             }  
  527.         }  
  528.     }  
  529.     else  
  530.     {   trace("Connect Immediately!!!\n");  
  531.         ret = true;  
  532.     }  
  533.   
  534.     argp = 0;  
  535.     ioctl(socketfd, FIONBIO, &argp);  
  536.   
  537.     if (!ret)  
  538.     {  
  539.         close(socketfd);  
  540.         fprintf(stderr, "cannot connect server!!\n");  
  541.         return -1;  
  542.     }  
  543.   
  544.     //fprintf(stdout, "Connect!!!\n");  
  545.   
  546.     return 0;  
  547. }  
  548.   
  549.   
  550. const std::string CFTPManager::serverResponse(int sockfd)  
  551. {  
  552.     if (sockfd == INVALID_SOCKET)  
  553.     {  
  554.         return "";  
  555.     }  
  556.       
  557.     int nRet = -1;  
  558.     char buf[MAX_PATH] = {0};  
  559.   
  560.     m_strResponse.clear();  
  561.   
  562.     while ((nRet = getData(sockfd, buf, MAX_PATH)) > 0)  
  563.     {  
  564.         buf[MAX_PATH - 1] = '\0';  
  565.         m_strResponse += buf;  
  566.     }  
  567.   
  568.     return m_strResponse;  
  569. }  
  570.   
  571. FTP_API CFTPManager::getData(int fd, char *strBuf, unsigned long length)  
  572. {  
  573.     assert(strBuf != NULL);  
  574.   
  575.     if (fd == INVALID_SOCKET)  
  576.     {  
  577.         return -1;  
  578.     }  
  579.   
  580.     memset(strBuf, 0, length);  
  581.     timeval stime;  
  582.     int nLen;  
  583.   
  584.     stime.tv_sec = 1;  
  585.     stime.tv_usec = 0;  
  586.   
  587.     fd_set  readfd;  
  588.     FD_ZERO( &readfd );  
  589.     FD_SET(fd, &readfd );  
  590.   
  591.     if (select(fd + 1, &readfd, 0, 0, &stime) > 0)  
  592.     {  
  593.         if ((nLen = recv(fd, strBuf, length, 0)) > 0)  
  594.         {  
  595.             return nLen;  
  596.         }  
  597.         else  
  598.         {  
  599.             return -2;  
  600.         }  
  601.     }  
  602.     return 0;  
  603. }  
  604.   
  605. FTP_API CFTPManager::Send(int fd, const std::string &cmd)  
  606. {  
  607.     if (fd == INVALID_SOCKET)  
  608.     {  
  609.         return -1;  
  610.     }  
  611.   
  612.     return Send(fd, cmd.c_str(), cmd.length());  
  613. }  
  614.   
  615. FTP_API CFTPManager::Send(int fd, const char *cmd, const size_t len)  
  616. {  
  617.     if((FTP_COMMAND_USERNAME != m_nCurrentCommand)   
  618.         &&(FTP_COMMAND_PASSWORD != m_nCurrentCommand)  
  619.         &&(!m_bLogin))  
  620.     {  
  621.         return -1;  
  622.     }  
  623.   
  624.     timeval timeout;  
  625.     timeout.tv_sec  = 1;  
  626.     timeout.tv_usec = 0;  
  627.   
  628.     fd_set  writefd;  
  629.     FD_ZERO(&writefd);    
  630.     FD_SET(fd, &writefd);  
  631.   
  632.     if(select(fd + 1, 0, &writefd , 0 , &timeout) > 0)  
  633.     {  
  634.         size_t nlen  = len;   
  635.         int nSendLen = 0;   
  636.         while (nlen >0)   
  637.         {  
  638.             nSendLen = send(fd, cmd , (int)nlen , 0);  
  639.   
  640.             if(nSendLen == -1)   
  641.                 return -2;   
  642.   
  643.             nlen = nlen - nSendLen;  
  644.             cmd +=  nSendLen;  
  645.         }  
  646.         return 0;  
  647.     }  
  648.     return -1;  
  649. }  
  650.   
  651.   
  652. FTP_API CFTPManager::createDataLink(int data_fd)  
  653. {  
  654.     assert(data_fd != INVALID_SOCKET);  
  655.   
  656.     std::string strData;  
  657.     unsigned long nPort = 0 ;  
  658.     std::string strServerIp ;   
  659.     std::list<std::string> strArray ;  
  660.   
  661.     std::string parseStr = Pasv();  
  662.   
  663.     if (parseStr.size() <= 0)  
  664.     {  
  665.         return -1;  
  666.     }  
  667.   
  668.     //trace("parseInfo: %s\n", parseStr.c_str());  
  669.   
  670.     size_t nBegin = parseStr.find_first_of("(");  
  671.     size_t nEnd   = parseStr.find_first_of(")");  
  672.     strData       = parseStr.substr(nBegin + 1, nEnd - nBegin - 1);  
  673.   
  674.     //trace("ParseAfter: %s\n", strData.c_str());  
  675.     if( SplitString( strData , strArray , "," ) <0)  
  676.         return -1;  
  677.   
  678.     if( ParseString( strArray , nPort , strServerIp) < 0)  
  679.         return -1;  
  680.   
  681.     //trace("nPort: %ld IP: %s\n", nPort, strServerIp.c_str());  
  682.   
  683.     if (Connect(data_fd, strServerIp, nPort) < 0)  
  684.     {  
  685.         return -1;  
  686.     }  
  687.   
  688.     return 0;  
  689.   
  690. }  
  691.   
  692. FTP_API CFTPManager::ParseString(std::list<std::string> strArray, unsigned long & nPort ,std::string & strServerIp)  
  693. {  
  694.     if (strArray.size() < 6 )  
  695.         return -1 ;  
  696.   
  697.     std::list<std::string>::iterator citor;  
  698.     citor = strArray.begin();  
  699.     strServerIp = *citor;  
  700.     strServerIp += ".";  
  701.     citor ++;  
  702.     strServerIp += *citor;  
  703.     strServerIp += ".";  
  704.     citor ++ ;  
  705.     strServerIp += *citor;  
  706.     strServerIp += ".";  
  707.     citor ++ ;  
  708.     strServerIp += *citor;  
  709.     citor = strArray.end();  
  710.     citor--;  
  711.     nPort = atol( (*citor).c_str());  
  712.     citor--;  
  713.     nPort += atol( (*(citor)).c_str()) * 256 ;  
  714.     return 0 ;   
  715. }  
  716.   
  717. FILE *CFTPManager::createLocalFile(const std::string &strLocalFile)  
  718. {  
  719.     return fopen(strLocalFile.c_str(), "w+b");  
  720. }  
  721.   
  722. FTP_API CFTPManager::downLoad(const std::string &strRemoteFile, const std::string &strLocalFile, const int pos, const unsigned int length)  
  723. {  
  724.     assert(length >= 0);  
  725.   
  726.     FILE *file = NULL;  
  727.     unsigned long nDataLen = FTP_DEFAULT_BUFFER;  
  728.     char strPos[MAX_PATH]  = {0};  
  729.     int data_fd = socket(AF_INET, SOCK_STREAM, 0);  
  730.       
  731.     assert(data_fd != -1);  
  732.   
  733.     if ((length != 0) && (length < nDataLen))  
  734.     {  
  735.         nDataLen = length;  
  736.     }  
  737.     char *dataBuf = new char[nDataLen];  
  738.     assert(dataBuf != NULL);  
  739.   
  740.     sprintf(strPos, "%d", pos);  
  741.   
  742.     if (createDataLink(data_fd) < 0)  
  743.     {  
  744.         trace("@@@@ Create Data Link error!!!\n");  
  745.         return -1;  
  746.     }  
  747.   
  748.     std::string strCmdLine = parseCommand(FTP_COMMAND_DOWNLOAD_POS, strPos);  
  749.     if (Send(m_cmdSocket, strCmdLine) < 0)  
  750.     {  
  751.         return -1;  
  752.     }  
  753.     trace("@@@@Response: %s\n", serverResponse(m_cmdSocket).c_str());  
  754.   
  755.     strCmdLine = parseCommand(FTP_COMMAND_DOWNLOAD_FILE, strRemoteFile);  
  756.   
  757.     if (Send(m_cmdSocket, strCmdLine) < 0)  
  758.     {  
  759.         return -1;  
  760.     }  
  761.     trace("@@@@Response: %s\n", serverResponse(m_cmdSocket).c_str());  
  762.   
  763.     file = createLocalFile(std::string(FTP_DEFAULT_PATH + strLocalFile));  
  764.     assert(file != NULL);  
  765.       
  766.     int len = 0;  
  767.     int nReceiveLen = 0;  
  768.     while ((len = getData(data_fd, dataBuf, nDataLen)) > 0)  
  769.     {  
  770.         nReceiveLen += len;  
  771.   
  772.         int num = fwrite(dataBuf, 1, len, file);  
  773.         memset(dataBuf, 0, sizeof(dataBuf));  
  774.       
  775.         //trace("%s", dataBuf);  
  776.         trace("Num:%d\n", num);  
  777.         if (nReceiveLen == length && length != 0)  
  778.             break;  
  779.   
  780.         if ((nReceiveLen + nDataLen) > length  && length != 0)  
  781.         {  
  782.             delete []dataBuf;  
  783.             nDataLen = length - nReceiveLen;  
  784.             dataBuf = new char[nDataLen];  
  785.         }  
  786.     }  
  787.   
  788.     Close(data_fd);  
  789.     fclose(file);  
  790.     delete []dataBuf;  
  791.   
  792.     return 0;  
  793. }  
  794.   
  795. FTP_API CFTPManager::parseResponse(const std::string &str)  
  796. {  
  797.     assert(!str.empty());  
  798.   
  799.     std::string strData = str.substr(0, 3);  
  800.     unsigned int val = atoi(strData.c_str());  
  801.   
  802.     return val;  
  803. }  

0 0
原创粉丝点击