unix平台下ftp客户端c++实现实例

此实例为unix平台下运行要想在window下运行,只需稍微改动几处即可。

1,文件描述符改为SOCKET

2,去除connect函数中的ictl()函数

3,默认路径修改

4,对于多个文件或者多个文件夹,可以先压缩,然后传送。此实现可根据put()函数改写一下;

PutCompressPackage(const std::string &strRemoteFile, const std::string &strLocalFile)
{
 std::string strCmdLine;
 const unsigned long dataLen = FTP_DEFAULT_BUFFER;
 char strBuf[dataLen] = {0};
 unsigned long nLen = 0;
 FILE *pFile = fopen(strLocalFile.c_str(), "rb");  // 以只读方式打开  且文件必须存在
 assert(pFile != NULL);

fseek(pFile, 0, SEEK_END);  //先指向文件末尾

unsigned long nSize = ftell(pFile); //计算文件长度

 int data_fd = socket(AF_INET, SOCK_STREAM, 0);
 assert(data_fd != -1);

 if (createDataLink(data_fd) < 0)
 {
  return -1;
 }


 strCmdLine = parseCommand(FTP_COMMAND_APPEND_FILE, strRemoteFile);

 if (Send(m_cmdSocket, strCmdLine) < 0)
 {
  Close(data_fd);
  return -1;
 }

 trace("@@@@Response: %s\n", serverResponse(m_cmdSocket).c_str());

 fseek(pFile, 0, SEEK_SET); //指向文件开始,后边用于读取。
 while (!feof(pFile))
 {
  nLen = fread(strBuf, 1, dataLen, pFile);
  if (nLen < 0)
  {
   break;
  }

  if (Send(data_fd, strBuf,nLen) < 0)    //不同于put函数,使用的是send函数的重载,必须带上长度!
  {
   Close(data_fd);
   return -1;
  }
 }

 trace("@@@@Response: %s\n", serverResponse(data_fd).c_str());

 Close(data_fd);
 trace("@@@@Response: %s\n", serverResponse(m_cmdSocket).c_str());
 fclose(pFile);

 return 0;
}

 

其余的地方根据自己的情况自行修改下就可以直接在window下运行了。

#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\n", 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\n", 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\n", 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\n", 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\n", serverResponse(m_cmdSocket).c_str());
  close(dataSocket);
  return "";
 }
 else
 {
  trace("@@@@Response: %s\n", serverResponse(m_cmdSocket).c_str());
  m_strResponse = serverResponse(dataSocket);

  trace("@@@@Response: \n%s\n", 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\n", 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\n", 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\n", 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\n", 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\n", serverResponse(m_cmdSocket).c_str());

 Send(m_cmdSocket, parseCommand(FTP_COMMAND_RENAME_END, strNewFile));

 m_strResponse = serverResponse(m_cmdSocket);
 trace("@@@@Response: %s\n", 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\n", 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\n", 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\n", 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\n", 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\n", serverResponse(data_fd).c_str());

 Close(data_fd);
 trace("@@@@Response: %s\n", 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 += "\r\n";

 m_commandStr = strCommandLine;
 trace("parseCommand: %s\n", 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\n", 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!!!\n");
  ret = true;
 }

 argp = 0;
 ioctl(socketfd, FIONBIO, &argp);

 if (!ret)
 {
  close(socketfd);
  fprintf(stderr, "cannot connect server!!\n");
  return -1;
 }

 //fprintf(stdout, "Connect!!!\n");

 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] = '\0';
  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\n", 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\n", strData.c_str());
 if( SplitString( strData , strArray , "," ) <0)
  return -1;

 if( ParseString( strArray , nPort , strServerIp) < 0)
  return -1;

 //trace("nPort: %ld IP: %s\n", 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!!!\n");
  return -1;
 }

 std::string strCmdLine = parseCommand(FTP_COMMAND_DOWNLOAD_POS, strPos);
 if (Send(m_cmdSocket, strCmdLine) < 0)
 {
  return -1;
 }
 trace("@@@@Response: %s\n", serverResponse(m_cmdSocket).c_str());

 strCmdLine = parseCommand(FTP_COMMAND_DOWNLOAD_FILE, strRemoteFile);

 if (Send(m_cmdSocket, strCmdLine) < 0)
 {
  return -1;
 }
 trace("@@@@Response: %s\n", 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\n", 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;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值