zoukankan      html  css  js  c++  java
  • ftp 协议分析

    File Transfer Protocol(文件传输协议)

    使用SOCKET实现 FTP的客户端协议规则:

    .h

    #pragma once
    #include <string>
    #include <WinSock2.h>
    #include <iostream>
    #include <atlstr.h>
    #include <vector>
    
    
    using namespace std;
    
    #pragma comment(lib,"WS2_32.lib")
    
    
    struct StructUrlInfo{
    	string WebUrl;
    	string LocUrl;
    	string Fname;
    };
    struct ConFtpInfo 
    {
    	string Add;
    	string User;
    	string Pwd;
    	int    Port;
    	ConFtpInfo(string m_add,string m_user,string m_pwd,int m_port){
    		Add=m_add;
    		User=m_user;
    		Pwd=m_pwd;
    		Port=m_port;
    	}
    };
    
    
    class BZ_Ftp
    {
    public:
    	BZ_Ftp(void);
    	~BZ_Ftp(void);
    
    public:
    	SOCKET controlSocket, dataSocket;
    
    public:
    	bool   Start(ConFtpInfo m_ConFtpInfo);
    	bool   RootFileList(ConFtpInfo m_ConFtpInfo,string & name);//获取根目录文件列表
    	bool   GetDirFileList(ConFtpInfo m_ConFtpInfo,string DirName,string &name); //获取传入目录列表
    	bool   GetCurrentpath(ConFtpInfo m_ConFtpInfo,string & name);//返回当前路径
    
    	bool   DownFile(ConFtpInfo m_ConFtpInfo,string DownUrl,string FileName,string StorageUrl);//下载单个文件
    	bool   GetFileNameSize(ConFtpInfo m_ConFtpInfo,unsigned long  &fsize,string DownUrl,string FileName);//获取单个文件大小
    	bool   CreateMultipleDirectory(const CString& szPath);
    	bool   DownAllFile(vector<StructUrlInfo>UpdateInfoVec);
    
    
    	unsigned long   GetDownFileSize();
    	unsigned long GFileSize;;
    protected:
    	int  getStateCode(char* buf);
    	bool executeFTPCmd(SOCKET controlSocket, char* buf, int len, int stateCode);
    	int  getPortNum(char* buf);
    	unsigned long DownFileSize;
    	
    
    };
    

      .cpp

    #include "StdAfx.h"
    #include "BZ_Ftp.h"
    #include <vector>
    
    
    #define RECVPACK_SIZE 2048
    #define MAXBLOCKSIZE 1024
    
    
    BZ_Ftp::BZ_Ftp(void)
    {
    	controlSocket=NULL;
    	dataSocket=NULL;
    }
    
    
    BZ_Ftp::~BZ_Ftp(void)
    {
    	closesocket(dataSocket);
    	closesocket(controlSocket);
    	WSACleanup();
    }
    
    bool BZ_Ftp::Start(ConFtpInfo m_ConFtpInfo)
    {
    	WSADATA dat;
    	SOCKADDR_IN serverAddr;
    	int dataPort, ret, stateCode;
    	char buf[100]={0}, sendBuf[1024]={0};
    
    	if (WSAStartup(MAKEWORD(2,2),&dat)!=0)	
    	{
    		cout<<"Init Falied: "<<GetLastError()<<endl;
    		return false;
    	}
    
    	controlSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    	if(controlSocket==INVALID_SOCKET)
    	{
    		cout<<"Creating Control Socket Failed: "<<GetLastError()<<endl;
    		return false;
    	}
    
    	serverAddr.sin_family=AF_INET;
    	serverAddr.sin_addr.S_un.S_addr=inet_addr(m_ConFtpInfo.Add.c_str());	
    	serverAddr.sin_port=htons(m_ConFtpInfo.Port);			
    	memset(serverAddr.sin_zero,0,sizeof(serverAddr.sin_zero));
    
    	ret=connect(controlSocket,(struct sockaddr*)&serverAddr,sizeof(serverAddr));
    	if(ret==SOCKET_ERROR)
    	{
    		cout<<"Control Socket connecting Failed: "<<GetLastError()<<endl;
    		return false;
    	}
    
    	cout<<"Control Socket connecting is success."<<endl;
    
    
    	recv(controlSocket,buf,100,0);
    
    	cout<<buf;
    
    	if(getStateCode(buf) != 220)
    	{
    		cout<<"Error: Control Socket connecting Failed"<<endl;
    		return false;
    	}
    
    	memset(buf,0,100);
    	sprintf(buf,"USER %s
    ",m_ConFtpInfo.User.c_str());
    	executeFTPCmd(controlSocket, buf, 100, 331);				//331
    
    	memset(buf,0,100);
    	sprintf(buf,"PASS %s
    ",m_ConFtpInfo.Pwd.c_str());
    	executeFTPCmd(controlSocket, buf, 100, 230);			//230
    	return true;
    }
    
    int BZ_Ftp::getStateCode( char* buf )
    {
    	int num=0;
    	char* p=buf;
    	while(p != NULL)
    	{
    		num=10*num+(*p)-'0';
    		p++;
    		if(*p==' '||*p=='-')
    		{
    			break;
    		}
    	}
    
    	return num;
    }
    
    bool BZ_Ftp::executeFTPCmd( SOCKET controlSocket, char* buf, int len, int stateCode )
    {
    	send(controlSocket, buf, len, 0);
    	memset(buf, 0, len);
    	recv(controlSocket, buf, 100, 0);
    	cout<<buf;
    	if(getStateCode(buf) == stateCode||getStateCode(buf)==226||getStateCode(buf)==250||getStateCode(buf)==150)
    	{
    		return true;
    	}
    	else
    	{
    		cout<<"The StateCode is Error!"<<endl;
    		return false;
    	}
    }
    
    int BZ_Ftp::getPortNum( char* buf )
    {
    	int num1=0,num2=0;
    	char* p=buf;
    	int cnt=0;
    	while( 1 )
    	{
    		if(cnt == 4 && (*p) != ',')
    		{
    			num1 = 10*num1+(*p)-'0';
    		}
    		if(cnt == 5)
    		{
    			num2 = 10*num2+(*p)-'0';
    		}
    		if((*p) == ',')
    		{
    			cnt++;
    		}
    		p++;
    		if((*p) == ')')
    		{
    			break;
    		}
    	}
    	cout<<"The data port number is "<<num1*256+num2<<endl;
    	return num1*256+num2;
    }
    
    bool BZ_Ftp::RootFileList(ConFtpInfo m_ConFtpInfo, string &strRes )
    {
    	char buffer[1024];
    	char buf[100];
    	int dataPort, ret, stateCode;	
    	bool res;
    
    	return 0;
    }
    
    bool BZ_Ftp::GetDirFileList( ConFtpInfo m_ConFtpInfo,string DirName,string &strRes )
    {
    	Start(m_ConFtpInfo);
    	
    	char buf[100];
    	int dataPort;
    	SOCKADDR_IN serverAddr;
    	memset(buf,0,100);
    	sprintf(buf,"PASV
    ");
    	executeFTPCmd(controlSocket, buf, 100, 227);				
    
    	dataPort=getPortNum(buf);
    	//???????socket
    	dataSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    	serverAddr.sin_family=AF_INET;
    	serverAddr.sin_addr.S_un.S_addr=inet_addr(m_ConFtpInfo.Add.c_str());
    	serverAddr.sin_port=htons(dataPort);	
    
    	int ret=connect(dataSocket,(struct sockaddr*)&serverAddr,sizeof(serverAddr));
    	if(ret==SOCKET_ERROR)
    	{
    		cout<<"Data Socket connecting Failed: "<<GetLastError()<<endl;
    		system("pause");
    		return -1;
    	}
    
    	
    	memset(buf,0,100);
    	sprintf(buf,"CWD %s
    ",DirName.c_str());//250
    	executeFTPCmd(controlSocket, buf, 100, 250);
    
    	
    	memset(buf,0,100);
    	sprintf(buf,"LIST%s
    ","");
    	executeFTPCmd(controlSocket, buf, 100, 150);						
    	memset(buf,0,100);
    	char buffer[1024];
    	memset(buffer,0,1024);
    
    	while(recv(dataSocket,buffer,100,0)){
    		strRes=strRes.append(buffer);
    		memset(buffer,0,1024);
    	}	
    
    	closesocket(dataSocket);
    	closesocket(controlSocket);
    
    	return true;
    }
    
    bool BZ_Ftp::GetCurrentpath( ConFtpInfo m_ConFtpInfo,string & name )
    {
    	Start(m_ConFtpInfo);
    	char buf[100];
    	string UrlStr;
    	memset(buf,0,100);
    	sprintf(buf,"PWD
    ","");
    	executeFTPCmd(controlSocket, buf, 100, 257);	
    
    	UrlStr.append(buf);
    
    	int index=UrlStr.find('"');
    	int index2=UrlStr.find('"',index+1);
    
    	name=UrlStr.substr(index+1,index2-index-1);
    
    	closesocket(controlSocket);
    
    	return true;
    }
    
    bool BZ_Ftp::DownFile( ConFtpInfo m_ConFtpInfo,string DownUrl,string FileName,string StorageUrl )
    {
    	if (!Start(m_ConFtpInfo))
    	{
    		return false;
    	}
    	
    	DownFileSize=0;
    
    	char buf[100];
    	char buffer[1024];
    	memset(buffer,0,1024);
    
    	int dataPort;
    	SOCKADDR_IN serverAddr;
    	memset(buf,0,100);
    	sprintf(buf,"PASV
    ");
    
    	if(!executeFTPCmd(controlSocket, buf, 100, 227)){
    
    		return false;
    	}			
    
    	dataPort=getPortNum(buf);
    	//???????socket
    	dataSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    	serverAddr.sin_family=AF_INET;
    	serverAddr.sin_addr.S_un.S_addr=inet_addr(m_ConFtpInfo.Add.c_str());	//??
    	serverAddr.sin_port=htons(dataPort);	
    
    	int ret=connect(dataSocket,(struct sockaddr*)&serverAddr,sizeof(serverAddr));
    	if(ret==SOCKET_ERROR)
    	{
    		cout<<"Data Socket connecting Failed: "<<GetLastError()<<endl;
    		return -1;
    	}
    
    
    	if (DownUrl[0]=='/')
    	{
    		DownUrl=DownUrl.substr(1,DownUrl.length());
    	}
    
    
    
    	string UrlStr;
    	memset(buf,0,100);
    	sprintf(buf,"CWD %s
    ",DownUrl.c_str());
    	if(!executeFTPCmd(controlSocket, buf, 100, 250)){
    		return false;
    	}	
    
    	memset(buf,0,100);
    	sprintf(buf,"TYPE I
    ");
    	if(!executeFTPCmd(controlSocket, buf, 100, 200)){
    		return false;
    	}				//200
    
    	memset(buf,0,100);
    	sprintf(buf,"RETR %s
    ",FileName.c_str());
    	if(!executeFTPCmd(controlSocket, buf, 100, 257)){
    		return false;
    	}	
    
    	memset(buf,0,100);
    	sprintf(buf,"TYPE I
    ");
    	if(!executeFTPCmd(controlSocket, buf, 100, 200)){
    		return false;
    	}				//200
    
    	//FileUrlCreat(StorageUrl.c_str());
    	CreateMultipleDirectory(StorageUrl.c_str());
    
    	string m_FileName;
    
    	if (StorageUrl.length()!=0)
    	{
    		if (StorageUrl[StorageUrl.length()-1]=='/')
    		{
    			m_FileName=StorageUrl+FileName.c_str();
    
    		}else{
    
    			m_FileName=StorageUrl+'\'+FileName.c_str();
    		}
    
    	}else{
    
    		m_FileName=FileName.c_str();
    	}
    
    
    	FILE * fp = fopen(m_FileName.c_str(),"wb");  
    	int err=GetLastError();
    
    	if(NULL == fp )  
    	{ 
    		printf("Down Fopen File Err Code:%d",err);
    		return false;
    	}  
    
    	int length = 0; 
    
    	while( 0!= (length = recv(dataSocket,buffer,1024,0)))  
    	{  
    		printf("recv  %d
    ",length);  
    
    		if(length < 0)  
    		{  	  
    			break;  
    		}  
    
    		int write_length = fwrite(buffer,sizeof(char),length,fp);  
    
    		DownFileSize=DownFileSize+write_length;
    
    		if (write_length<length)  
    		{  
    
    			break;  
    		}  
    
    		memset(buffer,0,1024);      
    	}  
    
    
    	fclose(fp);  
    
    	Sleep(100);
    
    	return true;
    }
    
    bool BZ_Ftp::GetFileNameSize( ConFtpInfo m_ConFtpInfo,unsigned long &fsize,string DownUrl,string FileName )
    {
    	Start(m_ConFtpInfo);
    	char buf[100];
    	
    	string UrlStr;
    	memset(buf,0,100);
    	sprintf(buf,"CWD %s
    ",DownUrl.c_str());
    	if(!executeFTPCmd(controlSocket, buf, 100, 257)){
    		return false;
    	}	
    
    	memset(buf,0,100);
    	sprintf(buf,"SIZE %s
    ",FileName.c_str());
    	if(!executeFTPCmd(controlSocket, buf, 100, 213)){
    		return false;
    	}
    
    
    	UrlStr=buf;
    
    	int index=UrlStr.find(" ");
    
    	UrlStr=UrlStr.substr(index+1,UrlStr.length());
    
    	fsize=atoi(UrlStr.c_str());
    
    	return true;
    }
    
    unsigned long BZ_Ftp::GetDownFileSize()
    {
    	return DownFileSize;
    }
    
    
    
    
    bool BZ_Ftp::CreateMultipleDirectory( const CString& szPath )
    {
    	CString strDir(szPath); 
    	if (strDir.Right(1) != "\")
    	{
    		strDir.AppendChar('\');
    	}
    
    	vector<CString> vPath;          
    	CString strTemp;               
    	BOOL bSuccess = FALSE;         
    
    
    	for (int i=0; i<strDir.GetLength(); ++i)
    	{
    		
    		if (strDir.GetAt(i) != '\') 
    		{
    			strTemp.AppendChar(strDir.GetAt(i));
    		}
    		else
    		{
    
    			vPath.push_back(strTemp);
    			strTemp.AppendChar('\');
    		}
    	}
    
    
    	std::vector<CString>::const_iterator vIter;
    
    	for (vIter = vPath.begin(); vIter != vPath.end(); vIter++) 
    	{
    		//??CreateDirectory????, ??TRUE,????FALSE
    		bSuccess = CreateDirectory(*vIter, NULL) ? TRUE : FALSE;    
    	}
    
    	return bSuccess;
    }
    

      调用示例:

    int _tmain(int argc, _TCHAR* argv[])
    {
        ConFtpInfo mConFtpInfo("192.168.1.233","root","root",21);
    
        BZ_Ftp  mBZ_Ftp;
    
        mBZ_Ftp.Start(mConFtpInfo);//连接登录FTP
    
        return 0;      
    }
    

     大家自己可以查阅FPT协议命令 实现更多的功能。 

      协议重点注意:

      21端口 只是ftp登录验证账号密码的端口,验证通过之后,服务端会返回 一个新的数据(也就是端口 num1*256+num2 =新端口) 给客户端 重新连接 ,用这个新的端口就可以进行数据的传输服务。 

         如有疑问欢迎联系我QQ:1930932008   备注博客园

  • 相关阅读:
    前端使用crypto.js进行加密
    C#编程总结(七)数据加密——附源码
    PID file /run/zabbix/zabbix_server.pid not readable (yet?) after start. 报错解决
    TNS-12560: Message 12560 not found; No message file for product=network, facility=TNS报错
    oracle无法启动asm实例记录
    linux添加硬盘分区挂载教程
    Oracle Database 12c Release 2安装过程实录
    Centos6.9minimal版系统安装图形化界面
    扫描工具nmap介绍
    Zabbix系列之六——添加web监测
  • 原文地址:https://www.cnblogs.com/xuandi/p/6739032.html
Copyright © 2011-2022 走看看