本文共 7923 字,大约阅读时间需要 26 分钟。
为了让大家更好的理解我发表的<FTP多线程>>,我把我自己编写的CMultiFTP类贴上来。这段代码我不是很满意(以前写的,请写的较仓促),
但主要供大家参考,更好得理解多线程下载的实现。 // MultiFTP1.cpp: implementation of the CMultiFTP class./////*#include "stdafx.h"
#include "MultiFTP.h"#include "MultiFTP1.h"#include#ifdef _DE
#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif//
// Construction/Destruction//#define BUFFERSIZE 5000CCriticalSection 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;} classCFTPGetFile::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/10748419/viewspace-983499/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/10748419/viewspace-983499/