CMultiFTP類原始碼 (轉)

worldblog發表於2007-12-04
CMultiFTP類原始碼 (轉)[@more@]

為了讓大家更好的理解我發表的<>,我把我自己編寫的CMultiFTP類貼上來。這段程式碼我不是很滿意(以前寫的,請寫的較倉促),
但主要供大家參考,更好得理解多執行緒下載的實現。


// MultiFTP1.cpp: implementation of the CMultiFTP class.
//
//////////////////////////////////////////////////////////////////////
/*

#include "stdafx.h"
#include "MultiFTP.h"
#include "MultiFTP1.h"
#include

#ifdef _DE
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define BUFFERSIZE 5000
CCriticalSection gcs_multiftp;
struct stThreadParam
{
 CString szLocalname;
 CString szRemotename;
 CString szHost;
 CString szUsername,szPass;
 int ID;
 int nPort;
 CMultiFTP *pFtp;
 UINT uStart,uLength;
};

UINT Thread(LPVOID pVoid)
{
 stThreadParam *pvar=(stThreadParam *)pVoid;
 int ID=pvar->ID ,nPort=pvar->nPort;
 CString szLocalname=pvar->szLocalname,szRemotename=pvar->szRemotename;
 CString szHost=pvar->szHost ;
 CString szUsername=pvar->szUsername ,szPassword=pvar->szPassword ;
 CMultiFTP *pFtp=pvar->pFtp;
 UINT uStart=pvar->uStart ,uLength=pvar->uLength;
 delete pvar;
  over
 
 CString szMsg;
 CFTPGetFile m_getfile(pFtp);
 CFile m_file;
 char *pBuffer;

 if(!m_getfile.Connect(szHost,nPort,szUsername,szPassword))
 {
 szMsg.Format("connect to data port failrnID:%drnError:%s",ID,m_getfile.szMsg);
 AfxMessageBox(szMsg);
 return 0;
 }
 m_file.Open(szLocalname,CFile::modeWrite|CFile::modeCreate);
 pBuffer=(char *)VirtualAlloc(NULL,uLength,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
 ASSERT(pBuffer);
 if(!m_getfile.OpenFile(szRemotename,szLocalname,uStart,uLength))
 {
 m_file.Close();
 DeleteFile(szLocalname);
 VirtualFree(pBuffer,0,MEM_RELEASE);
 szMsg.Format("open file failrnID:%drnError:%s",ID,m_getfile.szMsg);
 AfxMessageBox(szMsg);
 return 0;
 }
  file contents
 for(UINT uRead;uLength;uLength-=uRead)
 {
 uRead=m_getfile.Read(pBuffer,uLength);
 m_file.Write(pBuffer,uRead);
 }
 m_file.Close();
 VirtualFree(pBuffer,0,MEM_RELEASE);
 
 gcs_multiftp.Lock();
 pFtp->OnThreadOver(ID,0,"ok");
 gcs_multiftp.Unlock();
 
 return 0;
}


CMultiFTP::CMultiFTP()
{
 skClient.Create();
 nThreads=1;
 blContinue=FALSE;
}

CMultiFTP::~CMultiFTP()
{
 skClient.ShutDown(2);
 skClient.Close();
}

int CMultiFTP::GetThreads()
{
 return nThreads;
}

int CMultiFTP::SetThreads(int n)
{
 if(blContinue)
 nThreads=n;
 return nThreads;
}

BOOL CMultiFTP::Connect(CString szHost, UINT Port, CString szUser, CString szPass)
{
 ASSERT(skClient.m_hSocket);
 szHostname=szHost;
 nPort=Port;
 szUsername=szUser;
 szPassword=szPass;
 
 szMsg=="";
 if(!skClient.Connect(szHostname,nPort))
 {
 return FALSE;
 }
 GetMsg();

 CString szCommand;
 szCommand.Format("user %srn",szUsername);
 DoCommand(szCommand);
 szCommand.Format("pass %s",szPassword);
 if(DoCommand(szCommand)!=FTP_LOGOK)
 return FALSE;
 if(szMsg[3]=='-')
 GetMsg();
 if(DoCommand("rest 100")==FTP_RESTOK)
 {
 blContinue=TRUE;
 }
 else
 {
 nThreads=1;
 blContinue=FALSE;
 }
 DoCommand("type a");

 return TRUE;
}

void CMultiFTP::GetMsg()
{
 szMsg="";
 char chMsg[256];
 int nRecv;

  nRecv=skClient.Receive(chMsg,255);
 if(nRecv==SOCKET_ERROR || nRecv==0) return;
 chMsg[nRecv]='';
 szMsg=chMsg;
}

int CMultiFTP::GetReturnCode()
{
 CString szTemp=szMsg;
 szTemp.TrimLeft();
 return atoi(szTemp.Left(3));
}

 

int CMultiFTP::DoCommand(CString szCommand)
{
 szCommand+="rn";
 if(skClient.Send((LPCTSTR)szCommand,szCommand.GetLength())==SOCKET_ERROR)
 return SOCKET_ERROR;
 GetMsg();
 return GetReturnCode();
}

void CMultiFTP::Close()
{
 skClient.ShutDown(2);
 skClient.Close();
}

BOOL CMultiFTP::Intinue()
{
 return blContinue;
}

void CMultiFTP::OnThreadOver(int ID, UINT uRecv,CString szMsg)
{
 nThreadOvered++;
 if(nThreadOvered==nThreads)
 {
 if(Merge())
 AfxMessageBox("download over");
 else
 AfxMessageBox("download fail");
 }
}

 

BOOL CMultiFTP::Get(CString szRemotepath, CString szLocalpath)
{
 stThreadParam *pvar;
 
 CString szCommand;
 szCommand.Format("size %s",szRemotepath);
 if(DoCommand(szCommand)!=FTP_SIZEOK)
 return FALSE;
 szMsg.Delete(0,4);
 UINT uSize=atoi(szMsg),uAvgSize=uSize/nThreads,uStart=0;
 
 nThreadOvered=0;
 for(int i=1;i<=nThreads;i++)
 {
 pvar=new stThreadParam;
 pvar->ID =i;
  pvar->nPort =nPort;
 pvar->pFtp =this;
 pvar->szHost =szHostname;
 pvar->szPassword =szPassword;
 pvar->szUsername =szUsername;
 pvar->szLocalname.Format("%s_%d.dat",szLocalpath,i);
 pvar->szRemotename =szRemotepath;
 pvar->uStart =uStart;
 pvar->uLength =(i==nThreads)?uSize:uAvgSize;

 uStart+=pvar->uLength ;
 uSize-=uAvgSize;
 AfxBeginThread(DownloadThread,pvar);
 }

 szLocalname=szLocalpath;
 return TRUE;
}


class
CFTPGetFile::CFTPGetFile(CMultiFTP *pFtp2)
{
 pFtp=pFtp2;
 blFileopened=FALSE;
}

CFTPGetFile::~CFTPGetFile()
{
 Close();
}

BOOL CFTPGetFile::OpenFile(CString szRemotename,CString szLocalname,UINT uStart2,UINT uLength2)
{
 ASSERT(skClient.m_hSocket);
 if(skData.m_hSocket)
 skData.Close();
 
 uStart=uStart2;
 uLength=uLength2;
 CString szCommand,szHost;
 int iPort;

  remote file
  data traner port
 if(DoCommand("pasvrn")!=FTP_PASVOK)
 {
 szMsg.Format("openfile:pasv command fail,code:%d",GetFtpCode());
 AfxMessageBox(szMsg);
 return FALSE;
 }
 int p1,p2,i1,i2;
 int iStart=szMsg.ReverseFind('(');
 for(int i=iStart,count=0;i {
 if(szMsg[i]==',')
 {
 count++;
 if(count==4) p1=i+1;
 if(count==5) p2=i-1;
 }
 }
 i1=atoi(szMsg.Mid(p1,p2-p1+1));
 i2=atoi(szMsg.Mid(p2+2));
 iPort=(i1<<8)+i2;
 szHost=szMsg.Mid(iStart+1,p1-iStart-2);
 szHost.Replace(",",".");
  file mode to i
 DoCommand("type i");
  remote file pointer
 szCommand.Format("rest  %d",uStart);
 DoCommand(szCommand);
 ASSERT(GetFtpCode()==FTP_RESTOK);
  file command
 szCommand.Format("retr %s",szRemotename);
 DoCommand(szCommand,FALSE);

 skData.Create();
 if(!skData.Connect(szHost,iPort))
 {
 skData.Close();
 szMsg.Format("openfile:Connnect to data port:%d at server:%s fail",iPort,szHost);
 AfxMessageBox(szMsg);
 return FALSE;
 }
 
 return TRUE;
}

 


int CFTPGetFile::DoCommand(CString szCommand,BOOL blGetMsg)
{
 int nRecv;
 szCommand+="rn";
 skClient.Send((LPCTSTR)szCommand,szCommand.GetLength());
 if(blGetMsg)
 {
 nRecv=GetMsg();
  if(nRecv==0 || nRecv==SOCKET_ERROR)
 return nRecv;
  return GetFtpCode();
 }
 return 0;
}

int CFTPGetFile::GetFtpCode()
{
 szMsg.TrimLeft();
 return atoi(szMsg);
}

BOOL CFTPGetFile::Connect(CString szHostname, int iPort, CString szUser, CString szPass)
{
 if(skClient.m_hSocket)
 skClient.Close();
 skClient.Create();
 ASSERT(skClient.m_hSocket);
 if(!skClient.Connect(szHostname,iPort))
 {
 szMsg.Format("GetFile:connect to server fail:%d",GetLastError());
 AfxMessageBox(szMsg);
 Close();
 return FALSE;
 }
 
 CString szCommand;
 szCommand.Format("user %srn",szUser);
 DoCommand(szCommand);
 szCommand.Format("pass %srn",szPass);
 DoCommand(szCommand);
 if(szMsg[0]=='-')
 GetMsg();
 if(GetFtpCode()!=FTP_LOGOK)
 {
 szMsg.Format("GetFile:password is not correct");
 AfxMessageBox(szMsg);
 return FALSE;
 }
 DoCommand("type arn");

 return TRUE;
}

void CFTPGetFile::Close()
{
 if(skClient.m_hSocket)
 {
 skClient.ShutDown(2);
 skClient.Close();
 }
 if(skData.m_hSocket)
 {
 skData.ShutDown(2);
 skData.Close();
 }
}

int CFTPGetFile::GetMsg()
{
 int nRecv;
 szMsg="";
 nRecv=skClient.Receive(chRecv,255);
 if(nRecv==SOCKET_ERROR)
 return nRecv;
 chRecv[nRecv]='';
 szMsg=chRecv;

 return nRecv;
}

 

int CFTPGetFile::Read(char *pBuffer, int nBufferSize)
{
 return skData.Receive(pBuffer,nBufferSize);
}

BOOL CMultiFTP::Merge()
{
 CFileFind m_find;
 CString szFilename;
 DWORD dwSize;
 for(int i=1;i<=nThreads;i++)
 {
 szFilename.Format("%s_%d.dat",szLocalname,i);
 if(!m_find.FindFile(szFilename))
 return FALSE;
 if(i==nThreads)
 {
 m_find.FindNextFile();
 dwSize=m_find.GetLength();
 }
 m_find.Close();
 }


 CFile m_file,m_file2;
 char *pBuffer;
 pBuffer=(char *)VirtualAlloc(NULL,dwSize,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
 m_file.Open(szLocalname,CFile::modeCreate|CFile::modeWrite);
 for(i=1;i<=nThreads;i++)
 {
 szFilename.Format("%s_%d.dat",szLocalname,i);
 m_file2.Open(szFilename,CFile::modeRead);
 m_file2.Read(pBuffer,m_file2.GetLength()); 
 m_file.Write(pBuffer,m_file2.GetLength()); 
 m_file2.Close();
 // DeleteFile(szFilename);
 }
 m_file.Close();
 VirtualFree(pBuffer,0,MEM_RELEASE);
 return TRUE;
}


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987836/,如需轉載,請註明出處,否則將追究法律責任。

相關文章