📄 multiftp.cpp
字号:
this->FilePos = this->perFilePos = 0;
this->CreateNewFile(this->LocalLoad,this->fileSize);
DivisionFile(); ////
}
///////////////////////////////////////////////////////////
if(this->inforImpl.alreadyDownloadCnt >= this->fileSize)
{
fclose(globalFile);
DeleteFile(hisFileName);
closesocket(client);
return;
}
//////////////把文件分割成几块进行下载 ///////////
this->DoOnTextOut("下载的线程模块数为:"+IntToStr(this->FThreadCnt));
////////////////////////////启动线程0//////////////
MultiFtpDownloadThread *thread = new MultiFtpDownloadThread(true);
this->runningThreadCnt ++;
if(this->stop)
{
closesocket(client);
return;
}
thread->parent = this;
thread->commandClient = client;
thread->localFileLoad = this->FLocalLoad;
thread->FOnComplete = this->FOnComplete;
thread->FOnException = this->FOnException;
thread->FOnProgress = this->FOnProgress;
thread->FOnTextOut = this->FOnTextOut;
thread->FileName = this->FileName;
thread->Owner = this->Owner;
thread->perFileLen = this->PerGetLen;
thread->ID = 0;
thread->Resume();
//////////////////////////////////////////////////////
for(int i = 1; i < FThreadCnt ; i++)
{
SOCKET temp = this->ConnectFtp(this->FHost,this->FPort,this->FUserName,this->FPass);
this->CreateThread(i,temp);
}
////////////保证有多个线程同步下载/////////////
while(true && !this->stop)
{
if(this->runningThreadCnt < this->FThreadCnt)
{
if(this->FilePos >= this->fileSize)
return;
int successCode = this->GetSuccessCode(); //取得已经完成的线程id
int busyCode = this->GetBusyCode(); //取得任务最重的线程id
if((this->inforImpl.fromToImpl[busyCode].to - this->inforImpl.fromToImpl[busyCode].from)< (DWORD)this->PerGetLen )
{ //如果当前的文件下载字节比一次最小要取得的字节数还小,就退出
return;
}
AverageDownload(successCode,busyCode);
Sleep(1000);
}
else
{
Sleep(1000);
}
}
}
DWORD __fastcall TMultiFtp::GetFileSizeByName(String fileName)
{
FILE *file ;
DWORD dataLen;
file = fopen(fileName.c_str(),"r+b");
if(file == NULL) return 0;
fseek(file,0,2);
dataLen = ftell(file);
fclose(file);
return dataLen;
}
void __fastcall TMultiFtp::AverageDownload(int successCode , int busyCode)
{
DWORD per = (this->inforImpl.fromToImpl[busyCode].to - this->inforImpl.fromToImpl[busyCode].from - this->FPerGetLen) /2;
DWORD successFrom = this->inforImpl.fromToImpl[busyCode].to - per;
this->inforImpl.fromToImpl[successCode].from = successFrom;
this->inforImpl.fromToImpl[successCode].to = this->inforImpl.fromToImpl[busyCode].to;
this->inforImpl.fromToImpl[busyCode].to = successFrom;
SOCKET temp = this->ConnectFtp(this->FHost,this->FPort,this->FUserName,this->FPass); //开始下载
this->CreateThread(successCode,temp);
}
void __fastcall TMultiFtp::CreateThread(int code ,SOCKET client)
{
MultiFtpDownloadThread *thread = new MultiFtpDownloadThread(true);
this->runningThreadCnt ++;
this->SetCurrentDir(client,this->FilePath);
if(this->stop)
{
closesocket(client);
return;
}
thread->parent = this;
thread->commandClient = client;
thread->localFileLoad = this->FLocalLoad;
thread->FOnComplete = this->FOnComplete;
thread->FOnException = this->FOnException;
thread->FOnProgress = this->FOnProgress;
thread->FOnTextOut = this->FOnTextOut;
thread->FileName = this->FileName;
thread->Owner = this->Owner;
thread->perFileLen = this->PerGetLen;
thread->ID = code;
thread->Resume();
}
String __fastcall TMultiFtp::SetCurrentDir(SOCKET client ,String fileName)
{
int index;
index = fileName.Pos("/");
String temp;
char *buffer = new char[100];
while(index > 0)
{
temp = fileName.SubString(1,index-1);
String curDir = "PWD \r\n";
send(client,curDir.c_str(),curDir.Length(),0);
int recLen = recv(client,buffer,100,0);
buffer[recLen] = 0;
if(!this->ChangeDirectory(client,temp))
{
delete[] buffer;
return "";
}
fileName = fileName.SubString(index+1,fileName.Length()- index);
index = fileName.Pos("/");
}
delete[] buffer;
return fileName;
}
void __fastcall TMultiFtp::WriteToFile(String filePath,DWORD pos ,char *buffer , int len)
{
String tempFileName = filePath + ".nam";
while(isUseFile)
Sleep(50);
isUseFile = true;
FILE *file ;
file = fopen(tempFileName.c_str(),"r+b");
if(file == NULL) {
String str = this->FileName + ".san";
fclose(this->globalFile);
DeleteFile(str);
this->DoOnException("写入文件失败!");
isUseFile = false;
return;
} ;
fseek(file,pos,0);
fwrite(buffer,sizeof(char),len,file);
fclose(file);
isUseFile = false;
}
bool __fastcall TMultiFtp::CreateNewFile(String fileName, DWORD size)
{
String tempFileName = fileName + ".nam";
FILE *file;
file = fopen(tempFileName.c_str(),"w+b");
if(file == NULL) return false;
this->DoOnTextOut("正在创建文件,请稍候...");
char * buffer = new char[60000];
memset(buffer,'0',60000);
DWORD writeLen = 0;
int needLen = 60000;
while(writeLen < size)
{
if(writeLen + 60000 > size)
{
needLen = size -writeLen;
}
else
needLen = 60000;
int len = fwrite(buffer,sizeof(char),needLen,file);
if(len > 0) writeLen += len;
}
delete[] buffer;
fclose(file);
return true;
}
bool __fastcall TMultiFtp::WriteInforToFile()
{
String writeStr ;
String fileSizeStr = IntToStr(this->fileSize);
String threadCntStr = IntToStr(this->inforImpl.threadCnt);
String downloadCntStr = IntToStr(this->FilePos);
writeStr = this->LocalLoad+"\r\n"+fileSizeStr+"\r\n"+threadCntStr+"\r\n"+downloadCntStr+"\r\n";
for(int i = 0; i< this->inforImpl.threadCnt ; i++)
{
writeStr += IntToStr(this->inforImpl.fromToImpl[i].from) +"-"+IntToStr(this->inforImpl.fromToImpl[i].to)+"\r\n";
}
while(this->FileLocked) Sleep(10);
FileLocked = true;
if(this->globalFile == NULL)
{
FileLocked = false;
return false;
}
try
{
fseek(this->globalFile,0,0);
fwrite(writeStr.c_str(),sizeof(char),writeStr.Length(),this->globalFile);
FileLocked = false;
return true;
}
catch(...)
{
FileLocked = false;
return false;
}
}
void __fastcall TMultiFtp::DivisionFile()
{
this->fromToImpl = new FromToImpl[this->FThreadCnt];
this->inforImpl.fileLoad = this->FLocalLoad;
this->inforImpl.fileSize = this->fileSize;
this->inforImpl.threadCnt = this->FThreadCnt;
this->inforImpl.alreadyDownloadCnt = this->FilePos;
this->inforImpl.fromToImpl = new FromToImpl[this->FThreadCnt];
DWORD perCnt = this->fileSize / this->FThreadCnt;
int i;
for(i = 0 ;i < this->FThreadCnt-1 ; i++)
{
this->inforImpl.fromToImpl[i].from = perCnt * i;
this->inforImpl.fromToImpl[i].to = perCnt*(i+1);
}
this->inforImpl.fromToImpl[i].from = perCnt*(i);
this->inforImpl.fromToImpl[i].to = this->fileSize;
this->WriteInforToFile();
}
void __fastcall TMultiFtp::DealTimer(MSG msg)
{
DWORD desLen = this->FilePos - this->perFilePos;
this->DoOnGetRate(desLen);
}
void __fastcall TMultiFtp::GetInfor(String fileName)
{
char *buffer = new char[5000];
while(this->FileLocked) Sleep(50);
this->FileLocked = true;
globalFile = fopen(fileName.c_str(),"r+b");
fseek(this->globalFile,0,2);
int fileLen = ftell(this->globalFile);
fseek(this->globalFile,0,0);
int readLen = fread(buffer,sizeof(char),fileLen,this->globalFile);
buffer[readLen] = 0;
String str(buffer);
this->hisFileStr = str;
delete[] buffer;
this->FileLocked = false;
CreateInforImpl(str);
}
void __fastcall TMultiFtp::CreateInforImplFromString(String inforStr)
{
int index;
String temp;
index = hisFileStr.Pos("\r\n");
this->FLocalLoad = hisFileStr.SubString(1,index-1); //获取了文件的保存地址
hisFileStr = hisFileStr.SubString(index+2,hisFileStr.Length()-index);
index = hisFileStr.Pos("\r\n");
this->fileSize = StrToInt(hisFileStr.SubString(1,index-1)); //获取了文件大小
hisFileStr = hisFileStr.SubString(index+2,hisFileStr.Length() -index);
index = hisFileStr.Pos("\r\n");
this->ThreadCnt = StrToInt(hisFileStr.SubString(1,index-1)); //获取了线程数目
hisFileStr = hisFileStr.SubString(index+2,hisFileStr.Length() - index);
index = hisFileStr.Pos("\r\n");
this->FilePos = StrToInt(hisFileStr.SubString(1,index-1)); //获取了已经下载文件的大小
hisFileStr = hisFileStr.SubString(index+2,hisFileStr.Length() - index);
////付值给全局变量
this->inforImpl.fromToImpl = new FromToImpl[ThreadCnt];
this->inforImpl.fileLoad = this->FLocalLoad;
this->inforImpl.fileSize = this->fileSize;
this->inforImpl.threadCnt = this->ThreadCnt;
this->inforImpl.alreadyDownloadCnt = this->FilePos;
String from ,to;
for(int i =0 ;i < this->ThreadCnt ; i++)
{
index = hisFileStr.Pos("\r\n");
temp = hisFileStr.SubString(1,index-1); // 获取from - to 值
hisFileStr = hisFileStr.SubString(index +2 ,hisFileStr.Length() - index);
index = temp.Pos("-");
from = temp.SubString(1,index-1);
to = temp.SubString(index+1,temp.Length() - index);
this->inforImpl.fromToImpl[i].from = StrToInt(from);
this->inforImpl.fromToImpl[i].to = StrToInt(to);
}
}
void __fastcall TMultiFtp::CreateInforImpl(String str)
{ //一些断点续传的参数
int index;
String temp;
index = hisFileStr.Pos("\r\n");
this->FLocalLoad = hisFileStr.SubString(1,index-1); //获取了文件的保存地址
hisFileStr = hisFileStr.SubString(index+2,hisFileStr.Length()-index);
index = hisFileStr.Pos("\r\n");
this->fileSize = StrToInt(hisFileStr.SubString(1,index-1)); //获取了文件大小
hisFileStr = hisFileStr.SubString(index+2,hisFileStr.Length() -index);
index = hisFileStr.Pos("\r\n");
this->ThreadCnt = StrToInt(hisFileStr.SubString(1,index-1)); //获取了线程数目
hisFileStr = hisFileStr.SubString(index+2,hisFileStr.Length() - index);
index = hisFileStr.Pos("\r\n");
this->FilePos = StrToInt(hisFileStr.SubString(1,index-1)); //获取了已经下载文件的大小
hisFileStr = hisFileStr.SubString(index+2,hisFileStr.Length() - index);
////付值给全局变量
this->inforImpl.fromToImpl = new FromToImpl[ThreadCnt];
this->inforImpl.fileLoad = this->FLocalLoad;
this->inforImpl.fileSize = this->fileSize;
this->inforImpl.threadCnt = this->ThreadCnt;
this->inforImpl.alreadyDownloadCnt = this->FilePos;
String from ,to;
for(int i =0 ;i < this->ThreadCnt ; i++)
{
index = hisFileStr.Pos("\r\n");
temp = hisFileStr.SubString(1,index-1); // 获取from - to 值
hisFileStr = hisFileStr.SubString(index +2 ,hisFileStr.Length() - index);
index = temp.Pos("-");
from = temp.SubString(1,index-1);
to = temp.SubString(index+1,temp.Length() - index);
this->inforImpl.fromToImpl[i].from = StrToInt(from);
this->inforImpl.fromToImpl[i].to = StrToInt(to);
}
}
int __fastcall TMultiFtp::GetSuccessCode() //返回已经完成的线程id
{
for(int i = 0 ;i < this->FThreadCnt; i ++)
{
if(this->inforImpl.fromToImpl[i].from == this->inforImpl.fromToImpl[i].to)
{
return i;
}
}
return -1;
}
int __fastcall TMultiFtp::GetBusyCode() //返回任务最多的线程id
{
int code = -1 ;
DWORD descLen =0 ;
for(int i = 0; i < this->FThreadCnt; i++)
{
if( (this->inforImpl.fromToImpl[i].to - this->inforImpl.fromToImpl[i].from ) > descLen)
{
descLen = this->inforImpl.fromToImpl[i].to - this->inforImpl.fromToImpl[i].from ;
code= i;
}
}
return code;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -