• C++实现ftp客户端


    #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;
    }


  • 相关阅读:
    js笔记4
    js笔记3
    js笔记2
    js笔记1
    前端笔记13
    (7)第3章的开始
    (6)第2章的尾巴~
    (5)自定义数据结构再探
    我的学习方法(6)
    (4)自定义数据结构初探
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318247.html
Copyright © 2020-2023  润新知