zoukankan      html  css  js  c++  java
  • C++实现ftp客户端

    C++实现ftp客户端
    原创The_King_Cloud 发布于2012-10-19 17:09:42 阅读数 26454  收藏
    展开
     
    #ifndef CLIENT_H_
    #define CLIENT_H_
     
    #include <sys/socket.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/ioctl.h>
    #include <netinet/in.h>
    #include <sys/stat.h>
    #include <netdb.h>
    #include <errno.h>
    #include <arpa/inet.h>
    #include <sys/stat.h>
    #include <string>
    #include <list>
     
     
    #define INVALID_SOCKET                -1
    #define FTP_API                        int
    #define MAX_PATH                    260
    #define trace                        printf
     
    #define FTP_PARAM_BASE
    #define FTP_DEFAULT_PORT            "21"                            //FTP默认端口号
    #define FTP_DEFAULT_BUFFER            1024*4                            //FTP下载缓冲默认大小
    #define FTP_DEFAULT_PATH            "/mnt/dvs/"                        //FTP默认保存路径
        
    #define FTP_COMMAND_BASE            1000
    #define FTP_COMMAND_END                FTP_COMMAND_BASE + 30
    #define FTP_COMMAND_USERNAME        FTP_COMMAND_BASE + 1            //用户名
    #define FTP_COMMAND_PASSWORD        FTP_COMMAND_BASE + 2            //密码
    #define FTP_COMMAND_QUIT            FTP_COMMAND_BASE + 3            //退出
    #define FTP_COMMAND_CURRENT_PATH    FTP_COMMAND_BASE + 4            // 获取文件路径
    #define FTP_COMMAND_TYPE_MODE        FTP_COMMAND_BASE + 5            // 改变传输模式
    #define FTP_COMMAND_PSAV_MODE        FTP_COMMAND_BASE + 6            // 被动端口模式
    #define FTP_COMMAND_DIR                FTP_COMMAND_BASE + 7            // 获取文件列表
    #define FTP_COMMAND_CHANGE_DIRECTORY FTP_COMMAND_BASE + 8            // 改变路径
    #define FTP_COMMAND_DELETE_FILE        FTP_COMMAND_BASE + 9            // 删除文件
    #define FTP_COMMAND_DELETE_DIRECTORY FTP_COMMAND_BASE + 10            // 删除目录/文件夹
    #define FTP_COMMAND_CREATE_DIRECTORY FTP_COMMAND_BASE + 11            // 创建目录/文件夹
    #define FTP_COMMAND_RENAME_BEGIN    FTP_COMMAND_BASE  +12            // 开始重命名
    #define FTP_COMMAND_RENAME_END      FTP_COMMAND_BASE + 13            // 重命名结束
    #define FTP_COMMAND_FILE_SIZE        FTP_COMMAND_BASE + 14            // 获取文件大小
    #define FTP_COMMAND_DOWNLOAD_POS    FTP_COMMAND_BASE + 15            // 下载文件从指定位置开始
    #define FTP_COMMAND_DOWNLOAD_FILE    FTP_COMMAND_BASE + 16            // 下载文件
    #define FTP_COMMAND_UPLOAD_FILE        FTP_COMMAND_BASE + 17            // 上传文件
    #define FTP_COMMAND_APPEND_FILE        FTP_COMMAND_BASE + 18            // 追加上载文件    
     
    /*          登陆步骤
            login2Server
                |
            inputUserName
                |
            inputPassWord
                |
              具体操作
                |
              quit
    */
     
    class CFTPManager 
    {
    public :
        
        enum type {
            binary = 0x31,
            ascii,
        };
        
        CFTPManager(void);
     
        virtual ~CFTPManager(void);
        
        // ! 登陆服务器
        FTP_API login2Server(const std::string &serverIP);
     
        // !输入用户名
        FTP_API inputUserName(const std::string &userName);
     
        // !输入密码
        FTP_API inputPassWord(const std::string &password);
     
        // !退出FTP
        FTP_API quitServer(void);
     
        // !命令: PWD
        const std::string PWD();
     
        // !设置传输格式 2进制  还是ascii方式传输
        FTP_API setTransferMode(type mode);
     
        // !设置为被动模式
        const std::string Pasv();
     
        // ! 命令: DIR
        const std::string Dir(const std::string &path);
     
        // !命令 : CD
        FTP_API CD(const std::string &path);
     
        // !删除文件
        FTP_API DeleteFile(const std::string &strRemoteFile);
     
        // ! 删除文件夹/目录
        FTP_API DeleteDirectory(const std::string &strRemoteDir);
     
        // ! 创建目录/文件夹
        FTP_API CreateDirectory(const std::string &strRemoteDir);
     
        // !重命名
        FTP_API Rename(const std::string &strRemoteFile, const std::string &strNewFile);
     
        // !获取文件大小
        long getFileLength(const std::string &strRemoteFile);
     
        // !关闭连接
        void Close(int sock);
     
        // 下载文件
        FTP_API Get(const std::string &strRemoteFile, const std::string &strLocalFile);
     
        // 上载文件  支持断电传送方式
        FTP_API Put(const std::string &strRemoteFile, const std::string &strLocalFile);
     
     
    private:
        // !合成发送到服务器的命令
        const std::string parseCommand(const unsigned int command, const std::string &strParam);
     
        // ! 建立连接
        FTP_API Connect(int socketfd, const std::string &serverIP, unsigned int nPort);
     
        // ! 返回服务器信息
        const std::string serverResponse(int sockfd);
     
        // !获取服务器数据
        FTP_API getData(int fd, char *strBuf, unsigned long length);
     
        // !发送命令
        FTP_API Send(int fd, const std::string &cmd);
     
        // !发送命令
        FTP_API Send(int fd, const char *cmd, const size_t len);
     
        // !建立数据连接
        FTP_API createDataLink(int data_fd);
     
        // !解析PASV模式返回的字符串获取FTP端口号和FTP服务器IP
        FTP_API ParseString(std::list<std::string> strArray, unsigned long & nPort ,std::string & strServerIp);
     
        // 打开本地文件
        FILE *createLocalFile(const std::string &strLocalFile);
     
        // 下载文件 
        FTP_API downLoad(const std::string &strRemoteFile, const std::string &strLocalFile, const int pos = 0, const unsigned int length = 0);
     
        // 解析返回ftp命令的值
        FTP_API parseResponse(const std::string &str);
     
    private:
        //!控制连接套接字
        int        m_cmdSocket;
        
        // !当前用户名
        std::string m_strUserName;
     
        // !当前用户密码
        std::string m_strPassWord;
     
        // !服务器的IP
        std::string m_strServerIP;
     
        // !服务器Port
        unsigned int m_nServerPort;
     
        // !服务器回应信息缓存
        std::string m_strResponse;
     
        // !保存命令参数
        std::string m_commandStr;
     
        // !当前使用的命令参数
        unsigned int m_nCurrentCommand;
     
        // !是否登陆标志。
        bool    m_bLogin;
    };
     
     
    #endif

    #include "../Source/FTPManager.h"
     
    static int SplitString( std::string strSrc, std::list<std::string> &strArray , std::string strFlag)
    {
        int pos = 1; 
     
        while((pos = (int)strSrc.find_first_of(strFlag.c_str())) > 0) 
        {
            strArray.insert(strArray.end(), strSrc.substr(0 , pos));
            strSrc = strSrc.substr(pos + 1, strSrc.length() - pos - 1); 
        }
     
        strArray.insert(strArray.end(), strSrc.substr(0, strSrc.length()));
     
        return 0; 
    }
     
    CFTPManager::CFTPManager(void): m_bLogin(false)
    {
        m_cmdSocket = socket(AF_INET, SOCK_STREAM, 0);
        
    }
     
    CFTPManager::~CFTPManager(void)
    {
        std::string strCmdLine = parseCommand(FTP_COMMAND_QUIT, "");
     
        Send(m_cmdSocket, strCmdLine.c_str());
        close(m_cmdSocket);
        m_bLogin = false;
    }
     
    FTP_API CFTPManager::login2Server(const std::string &serverIP)
    {
        std::string strPort;
        int pos = serverIP.find_first_of(":");
     
        if (pos > 0)
        {
            strPort = serverIP.substr(pos + 1, serverIP.length() - pos);
        }
        else
        {
            pos = serverIP.length();
            strPort = FTP_DEFAULT_PORT;
        }
     
        m_strServerIP = serverIP.substr(0, pos);
        m_nServerPort = atol(strPort.c_str());
     
        trace("IP: %s port: %d ", m_strServerIP.c_str(), m_nServerPort);
     
        if (Connect(m_cmdSocket, m_strServerIP, m_nServerPort) < 0)
        {
            
            return -1;
        }
        
        m_strResponse = serverResponse(m_cmdSocket);
        printf("@@@@Response: %s", m_strResponse.c_str());
     
        return    parseResponse(m_strResponse);
    }
     
    FTP_API CFTPManager::inputUserName(const std::string &userName)
    {
        std::string strCommandLine = parseCommand(FTP_COMMAND_USERNAME, userName);
     
        m_strUserName = userName;
     
        if (Send(m_cmdSocket, strCommandLine) < 0)
        {
            return -1;
        }
     
        m_strResponse = serverResponse(m_cmdSocket);
        printf("Response: %s ", m_strResponse.c_str());
     
        return parseResponse(m_strResponse);
    }
     
    FTP_API CFTPManager::inputPassWord(const std::string &password)
    {
        std::string strCmdLine = parseCommand(FTP_COMMAND_PASSWORD, password);
     
        m_strPassWord = password;
        if (Send(m_cmdSocket, strCmdLine) < 0)
        {
            return -1;
        }
        else
        {
            m_bLogin = true;
     
            m_strResponse = serverResponse(m_cmdSocket);
            printf("Response: %s ", m_strResponse.c_str());
     
            return parseResponse(m_strResponse);
        }
    }
     
    FTP_API CFTPManager::quitServer(void)
    {
        std::string strCmdLine = parseCommand(FTP_COMMAND_QUIT, "");
        if (Send(m_cmdSocket, strCmdLine) < 0)
        {
            return -1;
        }
        else
        {
            m_strResponse = serverResponse(m_cmdSocket);
            printf("Response: %s ", m_strResponse.c_str());
     
            return parseResponse(m_strResponse);
        }
     
    }
     
    const std::string CFTPManager::PWD()
    {
        std::string strCmdLine = parseCommand(FTP_COMMAND_CURRENT_PATH, "");
     
        if (Send(m_cmdSocket, strCmdLine.c_str()) < 0)
        {
            return "";
        }
        else
        {
            return serverResponse(m_cmdSocket);
        }
    }
     
     
    FTP_API CFTPManager::setTransferMode(type mode)
    {
        std::string strCmdLine;
     
        switch (mode)
        {
        case binary:
            strCmdLine = parseCommand(FTP_COMMAND_TYPE_MODE, "I");
            break;
        case ascii:
            strCmdLine = parseCommand(FTP_COMMAND_TYPE_MODE, "A");
            break;
        default:
            break;
        }
     
        if (Send(m_cmdSocket, strCmdLine.c_str()) < 0)
        {
            assert(false);
        }
        else
        {    
            m_strResponse  = serverResponse(m_cmdSocket);
            printf("@@@@Response: %s", m_strResponse.c_str());
     
            return parseResponse(m_strResponse);
        }
    }
     
     
    const std::string CFTPManager::Pasv()
    {
        std::string strCmdLine = parseCommand(FTP_COMMAND_PSAV_MODE, "");
     
        if (Send(m_cmdSocket, strCmdLine.c_str()) < 0)
        {
            return "";
        }
        else
        {
            m_strResponse = serverResponse(m_cmdSocket);
     
            return m_strResponse;
        }
    }
     
     
    const std::string CFTPManager::Dir(const std::string &path)
    {
        int dataSocket = socket(AF_INET, SOCK_STREAM, 0);
     
        if (createDataLink(dataSocket) < 0)
        {
            return "";
        }
        // 数据连接成功
        std::string strCmdLine = parseCommand(FTP_COMMAND_DIR, path);
     
        if (Send(m_cmdSocket, strCmdLine) < 0)
        {
            trace("@@@@Response: %s ", serverResponse(m_cmdSocket).c_str());
            close(dataSocket);
            return "";
        }
        else
        {
            trace("@@@@Response: %s ", serverResponse(m_cmdSocket).c_str());
            m_strResponse = serverResponse(dataSocket);
     
            trace("@@@@Response: %s ", m_strResponse.c_str());
            close(dataSocket);
     
            return m_strResponse;
        }
        
    }
     
     
    FTP_API CFTPManager::CD(const std::string &path)
    {
        assert(m_cmdSocket != INVALID_SOCKET);
     
        std::string strCmdLine = parseCommand(FTP_COMMAND_CHANGE_DIRECTORY, path);
     
        if (Send(m_cmdSocket, strCmdLine) < 0)
        {
            return -1;
        }
            
        m_strResponse = serverResponse(m_cmdSocket);
        
        trace("@@@@Response: %s ", m_strResponse.c_str());
        return parseResponse(m_strResponse);
    }
     
    FTP_API CFTPManager::DeleteFile(const std::string &strRemoteFile)
    {
        assert(m_cmdSocket != INVALID_SOCKET);
     
        std::string strCmdLine = parseCommand(FTP_COMMAND_DELETE_FILE, strRemoteFile);
     
        if (Send(m_cmdSocket, strCmdLine) < 0)
        {
            return -1;
        }
     
        m_strResponse = serverResponse(m_cmdSocket);
        printf("@@@@Response: %s ", m_strResponse.c_str());
        return parseResponse(m_strResponse);
    }
     
    FTP_API CFTPManager::DeleteDirectory(const std::string &strRemoteDir)
    {
        assert(m_cmdSocket != INVALID_SOCKET);
     
        std::string strCmdLine = parseCommand(FTP_COMMAND_DELETE_DIRECTORY, strRemoteDir);
     
        if (Send(m_cmdSocket, strCmdLine) < 0)
        {
            return -1;
        }
        
        m_strResponse = serverResponse(m_cmdSocket);
     
        trace("@@@@Response: %s ", m_strResponse.c_str());
        return parseResponse(m_strResponse);
    }
     
    FTP_API CFTPManager::CreateDirectory(const std::string &strRemoteDir)
    {
        assert(m_cmdSocket != INVALID_SOCKET);
     
        std::string strCmdLine = parseCommand(FTP_COMMAND_CREATE_DIRECTORY, strRemoteDir);
     
        if (Send(m_cmdSocket, strCmdLine) < 0)
        {
            return -1;
        }
        
        m_strResponse = serverResponse(m_cmdSocket);
     
        trace("@@@@Response: %s ", m_strResponse.c_str());
        return parseResponse(m_strResponse);
    }
     
    FTP_API CFTPManager::Rename(const std::string &strRemoteFile, const std::string &strNewFile)
    {
        assert(m_cmdSocket != INVALID_SOCKET);
     
        std::string strCmdLine = parseCommand(FTP_COMMAND_RENAME_BEGIN, strRemoteFile);
        Send(m_cmdSocket, strCmdLine);
        trace("@@@@Response: %s ", serverResponse(m_cmdSocket).c_str());
     
        Send(m_cmdSocket, parseCommand(FTP_COMMAND_RENAME_END, strNewFile));
     
        m_strResponse = serverResponse(m_cmdSocket);
        trace("@@@@Response: %s ", m_strResponse.c_str());
        return parseResponse(m_strResponse);
    }
     
    long CFTPManager::getFileLength(const std::string &strRemoteFile)
    {
        assert(m_cmdSocket != INVALID_SOCKET);
     
        std::string strCmdLine = parseCommand(FTP_COMMAND_FILE_SIZE, strRemoteFile);
     
        if (Send(m_cmdSocket, strCmdLine) < 0)
        {
            return -1;
        }
     
        m_strResponse = serverResponse(m_cmdSocket);
     
        trace("@@@@Response: %s ", m_strResponse.c_str());
     
        std::string strData = m_strResponse.substr(0, 3);
        unsigned long val = atol(strData.c_str());
     
        if (val == 213)
        {
            strData = m_strResponse.substr(4);
            trace("strData: %s ", strData.c_str());
            val = atol(strData.c_str());
     
            return val;
        }
     
        return -1;
    }
     
     
    void CFTPManager::Close(int sock)
    {
        shutdown(sock, SHUT_RDWR);
        close(sock);
        sock = INVALID_SOCKET;
    }
     
    FTP_API CFTPManager::Get(const std::string &strRemoteFile, const std::string &strLocalFile)
    {
        return downLoad(strRemoteFile, strLocalFile);
    }
     
     
    FTP_API CFTPManager::Put(const std::string &strRemoteFile, const std::string &strLocalFile)
    {
        std::string strCmdLine;
        const unsigned long dataLen = FTP_DEFAULT_BUFFER;
        char strBuf[dataLen] = {0};
        unsigned long nSize = getFileLength(strRemoteFile);
        unsigned long nLen = 0;
    //     struct stat sBuf;
    // 
    //     assert(stat(strLocalFile.c_str(), &sBuf) == 0);
    //     trace("size: %d ", sBuf.st_size);
     
        FILE *pFile = fopen(strLocalFile.c_str(), "rb");  // 以只读方式打开  且文件必须存在
        assert(pFile != NULL);
     
        int data_fd = socket(AF_INET, SOCK_STREAM, 0);
        assert(data_fd != -1);
     
        if (createDataLink(data_fd) < 0)
        {
            return -1;
        }
        
        if (nSize == -1)
        {
            strCmdLine = parseCommand(FTP_COMMAND_UPLOAD_FILE, strRemoteFile);
        }
        else
        {
            strCmdLine = parseCommand(FTP_COMMAND_APPEND_FILE, strRemoteFile);
        }
     
        if (Send(m_cmdSocket, strCmdLine) < 0)
        {
            Close(data_fd);
            return -1;
        }
     
        trace("@@@@Response: %s ", serverResponse(m_cmdSocket).c_str());
     
        fseek(pFile, nSize, SEEK_SET);
        while (!feof(pFile))
        {
            nLen = fread(strBuf, 1, dataLen, pFile);
            if (nLen < 0)
            {
                break;
            }
     
            if (Send(data_fd, strBuf) < 0)
            {
                Close(data_fd);
                return -1;
            }
        }
     
        trace("@@@@Response: %s ", serverResponse(data_fd).c_str());
     
        Close(data_fd);
        trace("@@@@Response: %s ", serverResponse(m_cmdSocket).c_str());
        fclose(pFile);
     
        return 0;
    }
     
    const std::string CFTPManager::parseCommand(const unsigned int command, const std::string &strParam)
    {
        if (command < FTP_COMMAND_BASE || command > FTP_COMMAND_END)
        {
            return "";
        }
     
        std::string strCommandLine;
     
        m_nCurrentCommand = command;
        m_commandStr.clear();
     
        switch (command)
        {
        case FTP_COMMAND_USERNAME:
            strCommandLine = "USER ";
            break;
        case FTP_COMMAND_PASSWORD:
            strCommandLine = "PASS ";
            break;
        case FTP_COMMAND_QUIT:
            strCommandLine = "QUIT ";
            break;
        case FTP_COMMAND_CURRENT_PATH:
            strCommandLine = "PWD ";
            break;
        case FTP_COMMAND_TYPE_MODE:
            strCommandLine = "TYPE ";
            break;
        case FTP_COMMAND_PSAV_MODE:
            strCommandLine = "PASV ";
            break;
        case FTP_COMMAND_DIR:
            strCommandLine = "LIST ";
            break;
        case FTP_COMMAND_CHANGE_DIRECTORY:
            strCommandLine = "CWD ";
            break;
        case FTP_COMMAND_DELETE_FILE:
            strCommandLine = "DELE ";
            break;
        case FTP_COMMAND_DELETE_DIRECTORY:
            strCommandLine = "RMD ";
            break;
        case FTP_COMMAND_CREATE_DIRECTORY:
            strCommandLine = "MKD ";
            break;
        case FTP_COMMAND_RENAME_BEGIN:
            strCommandLine = "RNFR ";
            break;
        case FTP_COMMAND_RENAME_END:
            strCommandLine = "RNTO ";
            break;
        case FTP_COMMAND_FILE_SIZE:
            strCommandLine = "SIZE ";
            break;
        case FTP_COMMAND_DOWNLOAD_FILE:
            strCommandLine = "RETR ";
            break;
        case FTP_COMMAND_DOWNLOAD_POS:
            strCommandLine = "REST ";
            break;
        case FTP_COMMAND_UPLOAD_FILE:
            strCommandLine = "STOR ";
            break;
        case FTP_COMMAND_APPEND_FILE:
            strCommandLine = "APPE ";
            break;
        default :
            break;
        }
     
        strCommandLine += strParam;
        strCommandLine += " ";
     
        m_commandStr = strCommandLine;
        trace("parseCommand: %s ", m_commandStr.c_str());
     
        return m_commandStr;
    }
     
    FTP_API CFTPManager::Connect(int socketfd, const std::string &serverIP, unsigned int nPort)
    {
        if (socketfd == INVALID_SOCKET)
        {
            return -1;
        }
     
        unsigned int argp = 1;
        int error = -1;
        int len = sizeof(int);
        struct sockaddr_in  addr;
        bool ret = false;
        timeval stime;
        fd_set  set;
     
        ioctl(socketfd, FIONBIO, &argp);  //设置为非阻塞模式
     
        memset(&addr, 0, sizeof(struct sockaddr_in));
        addr.sin_family = AF_INET;
        addr.sin_port    = htons(nPort);
        addr.sin_addr.s_addr = inet_addr(serverIP.c_str());
        bzero(&(addr.sin_zero), 8);
     
        trace("Address: %s %d ", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
        
        if (connect(socketfd, (struct sockaddr*)&addr, sizeof(struct sockaddr)) == -1)   //若直接返回 则说明正在进行TCP三次握手
        {
            stime.tv_sec = 20;  //设置为1秒超时
            stime.tv_usec = 0;
            FD_ZERO(&set);
            FD_SET(socketfd, &set);
     
            if (select(socketfd + 1, NULL, &set, NULL, &stime) > 0)   ///在这边等待 阻塞 返回可以读的描述符 或者超时返回0  或者出错返回-1
            {
                getsockopt(socketfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t*)&len);
                if (error == 0)
                {
                    ret = true;
                }
                else
                {
                    ret = false;
                }
            }
        }
        else
        {    trace("Connect Immediately!!! ");
            ret = true;
        }
     
        argp = 0;
        ioctl(socketfd, FIONBIO, &argp);
     
        if (!ret)
        {
            close(socketfd);
            fprintf(stderr, "cannot connect server!! ");
            return -1;
        }
     
        //fprintf(stdout, "Connect!!! ");
     
        return 0;
    }
     
     
    const std::string CFTPManager::serverResponse(int sockfd)
    {
        if (sockfd == INVALID_SOCKET)
        {
            return "";
        }
        
        int nRet = -1;
        char buf[MAX_PATH] = {0};
     
        m_strResponse.clear();
     
        while ((nRet = getData(sockfd, buf, MAX_PATH)) > 0)
        {
            buf[MAX_PATH - 1] = '';
            m_strResponse += buf;
        }
     
        return m_strResponse;
    }
     
    FTP_API CFTPManager::getData(int fd, char *strBuf, unsigned long length)
    {
        assert(strBuf != NULL);
     
        if (fd == INVALID_SOCKET)
        {
            return -1;
        }
     
        memset(strBuf, 0, length);
        timeval stime;
        int nLen;
     
        stime.tv_sec = 1;
        stime.tv_usec = 0;
     
        fd_set    readfd;
        FD_ZERO( &readfd );
        FD_SET(fd, &readfd );
     
        if (select(fd + 1, &readfd, 0, 0, &stime) > 0)
        {
            if ((nLen = recv(fd, strBuf, length, 0)) > 0)
            {
                return nLen;
            }
            else
            {
                return -2;
            }
        }
        return 0;
    }
     
    FTP_API CFTPManager::Send(int fd, const std::string &cmd)
    {
        if (fd == INVALID_SOCKET)
        {
            return -1;
        }
     
        return Send(fd, cmd.c_str(), cmd.length());
    }
     
    FTP_API CFTPManager::Send(int fd, const char *cmd, const size_t len)
    {
        if((FTP_COMMAND_USERNAME != m_nCurrentCommand) 
            &&(FTP_COMMAND_PASSWORD != m_nCurrentCommand)
            &&(!m_bLogin))
        {
            return -1;
        }
     
        timeval timeout;
        timeout.tv_sec  = 1;
        timeout.tv_usec = 0;
     
        fd_set  writefd;
        FD_ZERO(&writefd);  
        FD_SET(fd, &writefd);
     
        if(select(fd + 1, 0, &writefd , 0 , &timeout) > 0)
        {
            size_t nlen  = len; 
            int nSendLen = 0; 
            while (nlen >0) 
            {
                nSendLen = send(fd, cmd , (int)nlen , 0);
     
                if(nSendLen == -1) 
                    return -2; 
     
                nlen = nlen - nSendLen;
                cmd +=  nSendLen;
            }
            return 0;
        }
        return -1;
    }
     
     
    FTP_API CFTPManager::createDataLink(int data_fd)
    {
        assert(data_fd != INVALID_SOCKET);
     
        std::string strData;
        unsigned long nPort = 0 ;
        std::string strServerIp ; 
        std::list<std::string> strArray ;
     
        std::string parseStr = Pasv();
     
        if (parseStr.size() <= 0)
        {
            return -1;
        }
     
        //trace("parseInfo: %s ", parseStr.c_str());
     
        size_t nBegin = parseStr.find_first_of("(");
        size_t nEnd      = parseStr.find_first_of(")");
        strData          = parseStr.substr(nBegin + 1, nEnd - nBegin - 1);
     
        //trace("ParseAfter: %s ", strData.c_str());
        if( SplitString( strData , strArray , "," ) <0)
            return -1;
     
        if( ParseString( strArray , nPort , strServerIp) < 0)
            return -1;
     
        //trace("nPort: %ld IP: %s ", nPort, strServerIp.c_str());
     
        if (Connect(data_fd, strServerIp, nPort) < 0)
        {
            return -1;
        }
     
        return 0;
     
    }
     
    FTP_API CFTPManager::ParseString(std::list<std::string> strArray, unsigned long & nPort ,std::string & strServerIp)
    {
        if (strArray.size() < 6 )
            return -1 ;
     
        std::list<std::string>::iterator citor;
        citor = strArray.begin();
        strServerIp = *citor;
        strServerIp += ".";
        citor ++;
        strServerIp += *citor;
        strServerIp += ".";
        citor ++ ;
        strServerIp += *citor;
        strServerIp += ".";
        citor ++ ;
        strServerIp += *citor;
        citor = strArray.end();
        citor--;
        nPort = atol( (*citor).c_str());
        citor--;
        nPort += atol( (*(citor)).c_str()) * 256 ;
        return 0 ; 
    }
     
    FILE *CFTPManager::createLocalFile(const std::string &strLocalFile)
    {
        return fopen(strLocalFile.c_str(), "w+b");
    }
     
    FTP_API CFTPManager::downLoad(const std::string &strRemoteFile, const std::string &strLocalFile, const int pos, const unsigned int length)
    {
        assert(length >= 0);
     
        FILE *file = NULL;
        unsigned long nDataLen = FTP_DEFAULT_BUFFER;
        char strPos[MAX_PATH]  = {0};
        int data_fd = socket(AF_INET, SOCK_STREAM, 0);
        
        assert(data_fd != -1);
     
        if ((length != 0) && (length < nDataLen))
        {
            nDataLen = length;
        }
        char *dataBuf = new char[nDataLen];
        assert(dataBuf != NULL);
     
        sprintf(strPos, "%d", pos);
     
        if (createDataLink(data_fd) < 0)
        {
            trace("@@@@ Create Data Link error!!! ");
            return -1;
        }
     
        std::string strCmdLine = parseCommand(FTP_COMMAND_DOWNLOAD_POS, strPos);
        if (Send(m_cmdSocket, strCmdLine) < 0)
        {
            return -1;
        }
        trace("@@@@Response: %s ", serverResponse(m_cmdSocket).c_str());
     
        strCmdLine = parseCommand(FTP_COMMAND_DOWNLOAD_FILE, strRemoteFile);
     
        if (Send(m_cmdSocket, strCmdLine) < 0)
        {
            return -1;
        }
        trace("@@@@Response: %s ", serverResponse(m_cmdSocket).c_str());
     
        file = createLocalFile(std::string(FTP_DEFAULT_PATH + strLocalFile));
        assert(file != NULL);
        
        int len = 0;
        int nReceiveLen = 0;
        while ((len = getData(data_fd, dataBuf, nDataLen)) > 0)
        {
            nReceiveLen += len;
     
            int num = fwrite(dataBuf, 1, len, file);
            memset(dataBuf, 0, sizeof(dataBuf));
        
            //trace("%s", dataBuf);
            trace("Num:%d ", num);
            if (nReceiveLen == length && length != 0)
                break;
     
            if ((nReceiveLen + nDataLen) > length  && length != 0)
            {
                delete []dataBuf;
                nDataLen = length - nReceiveLen;
                dataBuf = new char[nDataLen];
            }
        }
     
        Close(data_fd);
        fclose(file);
        delete []dataBuf;
     
        return 0;
    }
     
    FTP_API CFTPManager::parseResponse(const std::string &str)
    {
        assert(!str.empty());
     
        std::string strData = str.substr(0, 3);
        unsigned int val = atoi(strData.c_str());
     
        return val;
    }


    ————————————————
    版权声明:本文为CSDN博主「The_King_Cloud」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/The_King_Cloud/article/details/8090699

  • 相关阅读:
    Java RunTime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. ......
    UVA 1597 Searching the Web
    UVA 1596 Bug Hunt
    UVA 230 Borrowers
    UVA 221 Urban Elevations
    UVA 814 The Letter Carrier's Rounds
    UVA 207 PGA Tour Prize Money
    UVA 1592 Database
    UVA 540 Team Queue
    UVA 12096 The SetStack Computer
  • 原文地址:https://www.cnblogs.com/grj001/p/12223102.html
Copyright © 2011-2022 走看看