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

  • 相关阅读:
    Luogu1053 NOIP2005篝火晚会
    BZOJ2151 种树(贪心+堆+链表/wqs二分+动态规划)
    Luogu1155 NOIP2008双栈排序(并查集)
    Luogu1092 NOIP2004虫食算(搜索+高斯消元)
    Codeforces Round#516 Div.1 翻车记
    Luogu1731 NOI1999生日蛋糕(搜索)
    洛谷 P1379 八数码难题 解题报告
    洛谷 P2501 [HAOI2006]数字序列 解题报告
    洛谷 P3143 [USACO16OPEN]钻石收藏家Diamond Collector 解题报告
    洛谷 P2894 [USACO08FEB]酒店Hotel 解题报告
  • 原文地址:https://www.cnblogs.com/grj001/p/12223102.html
Copyright © 2011-2022 走看看