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\r\n",m_ConFtpInfo.User.c_str());
executeFTPCmd(controlSocket, buf, 100, 331); //331 memset(buf,0,100);
sprintf(buf,"PASS %s\r\n",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\r\n");
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\r\n",DirName.c_str());//250
executeFTPCmd(controlSocket, buf, 100, 250); memset(buf,0,100);
sprintf(buf,"LIST%s\r\n","");
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\r\n","");
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\r\n"); 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\r\n",DownUrl.c_str());
if(!executeFTPCmd(controlSocket, buf, 100, 250)){
return false;
} memset(buf,0,100);
sprintf(buf,"TYPE I\r\n");
if(!executeFTPCmd(controlSocket, buf, 100, 200)){
return false;
} //200 memset(buf,0,100);
sprintf(buf,"RETR %s\r\n",FileName.c_str());
if(!executeFTPCmd(controlSocket, buf, 100, 257)){
return false;
} memset(buf,0,100);
sprintf(buf,"TYPE I\r\n");
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\n",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\r\n",DownUrl.c_str());
if(!executeFTPCmd(controlSocket, buf, 100, 257)){
return false;
} memset(buf,0,100);
sprintf(buf,"SIZE %s\r\n",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 备注博客园