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 备注博客园