📄 ftpget.cpp
字号:
// FtpGet.cpp: 实现CFtpGet类.
//
#include "stdafx.h"
#include "FtpGet.h"
#include "DealSocket.h"
#include "Myfile.h"
int CFtpGet::m_nCount;
//---------------------------------------------------------------------------
CFtpGet::CFtpGet()
{
}
//---------------------------------------------------------------------------
CFtpGet::~CFtpGet()
{
}
//---------------------------------------------------------------------------
void CFtpGet::DirList(SOCKET hCtrlSock,BOOL bPasvMode)
{
SOCKET hDataSock;
if(bPasvMode){
CString revStr=QueueFtpCmd(hCtrlSock,"PASV");
CString strHost=GetHost(revStr);
int nPort=GetPort(revStr);
hDataSock=dealsocket.GetConnect(strHost,nPort);
QueueFtpCmd(hCtrlSock,"LIST");
}
else{
SOCKET hLstnSock=InitPortConn(hCtrlSock);
QueueFtpCmd(hCtrlSock,"LIST");
hDataSock=accept(hLstnSock,0,0);
}
if(hDataSock == INVALID_SOCKET) return;
dealsocket.GetResponse(hDataSock);
}
//---------------------------------------------------------------------------
BOOL CFtpGet::FtpDownLoad(
CString strHostAddr,
int nPort,
CString strUserName ,
CString strPassword,
CString strFtpFileName,
CString strWriteFileName,
int nSectNum,
BOOL bPasvMode)
{
ASSERT(nSectNum>0);
SOCKET hCtrlSock=
ConnectFtp(strHostAddr,nPort,strUserName,strPassword);
// 下载类型.
QueueFtpCmd(hCtrlSock,"TYPE","I");
if(hCtrlSock == INVALID_SOCKET)
return FALSE;
// 获取被下载文件长度.
DWORD nFtpFileSize=GetFtpFileSize(hCtrlSock,strFtpFileName);
// 把计数器清零.
m_nCount=0;
// 给每个线程的信息结构申请内存.
sectinfo=new CFtpSect[nSectNum];
// 计算分割段的大小.
DWORD nSize = nFtpFileSize/nSectNum;
int i;
// 创建线程.
for(i=0;i<nSectNum;i++)
{
sectinfo[i].szHostAddr=strHostAddr;
sectinfo[i].szUserName=strUserName;
sectinfo[i].szPassword=strPassword;
sectinfo[i].nPort=nPort;
sectinfo[i].bPasvMode=bPasvMode;
sectinfo[i].szFtpFilename=strFtpFileName;
// 计算临时文件名.
CString strTempFileName;
strTempFileName.Format("%s_%d",strWriteFileName, i);
sectinfo[i].szDesFilename=strTempFileName;
if(i<nSectNum-1){
sectinfo[i].nStart=i*nSize;
sectinfo[i].nEnd=(i+1)*nSize;
}
else{
sectinfo[i].nStart=i*nSize;
sectinfo[i].nEnd=nFtpFileSize;
}
// AfxBeginThread(ThreadDownLoad,§info[i],THREAD_PRIORITY_HIGHEST);
AfxBeginThread(ThreadDownLoad,§info[i]);
}
// 等待所有线程结束.
while(m_nCount!=nSectNum);
FILE *fpwrite;
// 打开写文件.
if((fpwrite=fopen(strWriteFileName,"wb"))==NULL){
return FALSE;
}
for(i=0;i<nSectNum;i++)
{
FileCombine(§info[i],fpwrite);
}
fclose(fpwrite);
delete[] sectinfo;
return TRUE;
}
//---------------------------------------------------------------------------
UINT CFtpGet::ThreadDownLoad(void* pParam)
{
CFtpSect *pInfo=(CFtpSect*)pParam;
TRACE("Starting and ending pos: %s %d %d\n",
pInfo->szDesFilename, pInfo->nStart, pInfo->nEnd);
SOCKET hCtrlSock=ConnectFtp(pInfo->szHostAddr,pInfo->nPort,
pInfo->szUserName,pInfo->szPassword);
if(hCtrlSock == INVALID_SOCKET) return 1;
// 下载类型.
QueueFtpCmd(hCtrlSock,"TYPE","I");
// 计算临时文件大小.
DWORD nFileSize=myfile.GetFileSizeByName(pInfo->szDesFilename);
DWORD nSectSize=(pInfo->nEnd)-(pInfo->nStart);
// 此段已下载完毕.
if(nFileSize==nSectSize){
TRACE("文件已下载完毕!\n");
CFtpGet::m_nCount++; // 计数.
return 0;
}
FILE *fpwrite=myfile.GetFilePointer(pInfo->szDesFilename);
if(!fpwrite) return 1;
// 设置文件读取起始位置,请注意此命令所在位置的顺序.
SetFilePos(hCtrlSock,pInfo->nStart+nFileSize);
fseek(fpwrite,nFileSize,SEEK_SET);
SOCKET hDataSock;
if(pInfo->bPasvMode){
CString revStr=QueueFtpCmd(hCtrlSock,"PASV");
CString strHost=GetHost(revStr);
int nPort=GetPort(revStr);
if((hDataSock=dealsocket.GetConnect(strHost,nPort))
== INVALID_SOCKET) return 1;
QueueFtpCmd(hCtrlSock,"RETR",pInfo->szFtpFilename);
}
else{
SOCKET hLstnSock=InitPortConn(hCtrlSock);
QueueFtpCmd(hCtrlSock,"RETR",pInfo->szFtpFilename);
if((hDataSock=accept(hLstnSock,0,0))==INVALID_SOCKET)
return 1;
}
DWORD nLen;
DWORD nSumLen=0;
char szBuffer[1024];
while(1)
{
if(nSumLen>=nSectSize-nFileSize) break;
nLen=recv(hDataSock,szBuffer,sizeof(szBuffer),0);
if (nLen == SOCKET_ERROR){
TRACE("Read error!\n");
fclose(fpwrite);
return 1;
}
if(nLen==0) break;
nSumLen +=nLen;
TRACE("%d\n",nLen);
// 把数据写入文件.
fwrite(szBuffer,nLen,1,fpwrite);
}
// 关闭写文件.
fclose(fpwrite);
// 关闭套接字.
closesocket(hDataSock);
closesocket(hCtrlSock);
// 计数.
CFtpGet::m_nCount++;
return 0;
}
//---------------------------------------------------------------------------
BOOL CFtpGet::FileCombine(CFtpSect *pInfo, FILE *fpwrite)
{
FILE *fpread;
// 打开文件.
if((fpread=fopen(pInfo->szDesFilename,"rb"))==NULL)
return FALSE;
DWORD nPos=pInfo->nStart;
// 设置文件写指针起始位置.
fseek(fpwrite,nPos,SEEK_SET);
int c;
// 把文件数据写入到子文件.
while((c=fgetc(fpread))!=EOF)
{
fputc(c,fpwrite);
nPos++;
if(nPos==pInfo->nEnd) break;
}
fclose(fpread);
DeleteFile(pInfo->szDesFilename);
return TRUE;
}
//---------------------------------------------------------------------------
CString CFtpGet::QueueFtpCmd(SOCKET hSock,CString strCmd,CString strDescr)
{
CString str;
str.Format("%s %s\r\n",strCmd,strDescr);
send(hSock,str,str.GetLength(),0);
return dealsocket.GetResponse(hSock);
}
//---------------------------------------------------------------------------
CString CFtpGet::GetHost(CString pasvStr)
{
int index1 = pasvStr.Find("(");
int index2 = pasvStr.Find(")");
CString newstr=pasvStr.Mid(index1+1,index2-index1);
int a1,a2,a3,a4,p1,p2;
sscanf(newstr,"%d,%d,%d,%d,%d,%d",&a1,&a2,&a3,&a4,&p1,&p2);
CString strHost;
strHost.Format("%d.%d.%d.%d",a1,a2,a3,a4);
return strHost;
}
//---------------------------------------------------------------------------
int CFtpGet::GetPort(CString pasvStr)
{
int index1 = pasvStr.Find("(");
int index2 = pasvStr.Find(")");
CString newstr=pasvStr.Mid(index1+1,index2-index1);
int a1,a2,a3,a4,p1,p2;
sscanf(newstr,"%d,%d,%d,%d,%d,%d",&a1,&a2,&a3,&a4,&p1,&p2);
return p1*256 + p2;
}
//---------------------------------------------------------------------------
SOCKET CFtpGet::ConnectFtp(CString host,int port,CString userName,CString pass)
{
TRACE("正在建立连接\n");
SOCKET hCtrlSock=dealsocket.GetConnect(host,port);
if(hCtrlSock == INVALID_SOCKET){
TRACE("连接ftp服务器失败!\n");
return INVALID_SOCKET;
}
dealsocket.GetResponse(hCtrlSock);
CString revStr=QueueFtpCmd(hCtrlSock,"USER",userName);
if(GetCode(revStr) == 331)
{
TRACE("服务器要求验证密码...\n");
revStr=QueueFtpCmd(hCtrlSock,"PASS",pass);
int tryTimes = 3;
while(GetCode(revStr)!= 230 && tryTimes > 0)
{
revStr=QueueFtpCmd(hCtrlSock,"PASS",pass);
tryTimes--;
TRACE("第%d尝试\n",3-tryTimes);
}
if(tryTimes < 0)
{
TRACE(userName +"登录失败!\n");
return INVALID_SOCKET;
}
else
TRACE("登录成功!\n");
}
return hCtrlSock;
}
//---------------------------------------------------------------------------
DWORD CFtpGet::GetFtpFileSize(SOCKET hCtrlSock ,CString fileName)
{
CString revStr=QueueFtpCmd(hCtrlSock,"SIZE",fileName);
if(GetCode(revStr) != 213)
{
TRACE("尝试第二次获取\n");
revStr=QueueFtpCmd(hCtrlSock,"SIZE",fileName);
if(GetCode(revStr) != 213)
{
TRACE("尝试第三次获取\n");
revStr=QueueFtpCmd(hCtrlSock,"SIZE",fileName);
if(GetCode(revStr) != 213) {
TRACE("获取文件大小失败!");
return 0;
}
}
}
int index = revStr.Find("\r\n");
revStr = revStr.Mid(0,index);
index = revStr.Find(" ");
revStr = revStr.Mid(index,revStr.GetLength()- index);
DWORD fileSize =atoi(revStr);
return fileSize;
}
//---------------------------------------------------------------------------
BOOL CFtpGet::SetFilePos(SOCKET hCtrlSock,DWORD pos)
{
CString strPos;
strPos.Format("%d",pos);
CString revStr=QueueFtpCmd(hCtrlSock,"REST",strPos);
if(GetCode(revStr) != 350)
return FALSE;
return TRUE;
}
//---------------------------------------------------------------------------
UINT CFtpGet::GetCode(CString revStr)
{
if(revStr.IsEmpty()) return 0;
CString str;
int index ;
index = revStr.Find(" ");
str = revStr.Mid(0,index);
return atoi(str);
}
//---------------------------------------------------------------------------
SOCKET CFtpGet::InitPortConn(SOCKET hCtrlSock)
{
SOCKADDR_IN sockCtlAddr;
SOCKADDR_IN sockLsnAddr;
SOCKET hLstnSock=dealsocket.Listening(0);
int nLen = sizeof(SOCKADDR_IN);
if (hLstnSock == SOCKET_ERROR) {
closesocket(hLstnSock);
return INVALID_SOCKET;
}
if(getsockname(hLstnSock,(LPSOCKADDR)&sockLsnAddr,(int *)&nLen)
== SOCKET_ERROR)
{
return INVALID_SOCKET;
}
if(getsockname(hCtrlSock,(LPSOCKADDR)&sockCtlAddr,(int *)&nLen)
== SOCKET_ERROR)
{
return INVALID_SOCKET;
}
CString strPort;
strPort.Format("%d,%d,%d,%d,%d,%d",
sockCtlAddr.sin_addr.S_un.S_un_b.s_b1, // 本地地址.
sockCtlAddr.sin_addr.S_un.S_un_b.s_b2,
sockCtlAddr.sin_addr.S_un.S_un_b.s_b3,
sockCtlAddr.sin_addr.S_un.S_un_b.s_b4,
sockLsnAddr.sin_port & 0xFF, // 本地端口.
(sockLsnAddr.sin_port & 0xFF00)>>8);
QueueFtpCmd(hCtrlSock,"PORT",strPort);
return hLstnSock;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -