📄 sendfile_cpp.cpp
字号:
WriteFileSize=FileData.Position; //取出并保存文件长度
if (WriteListCount>0) delete [] WriteList;//删除文件块状态数据
WriteListCount=0; //清文件块状态数
div_t x;
x=div(WriteFileSize,1000); //计算文件块数量
WriteListCount=x.quot;
if (x.rem>0) WriteListCount++;
WriteList=new bool [WriteListCount];//建立文件块状态数组
for (int j=0;j<WriteListCount;j++) WriteList[j]=false;//置文件块状态
try
{
WriteFile=new TFileStream(GetDir()+"\\"+FileName,fmCreate|fmShareDenyNone);//建立文件
SendData_1("FRAll","",0); //向发送方发出读文件指令
}
catch (...)
{
FRStatusBar->Panels->Items[1]->Text="建立"+FileName+"失败";
SendData_1("FRErr","",0); //向发送方发出写文件失败信息
}
TimerCount=0; //文件传送计时器
Timer1->Enabled=true;
FRBlocks=0;
FRStatusBar->Panels->Items[2]->Text="00:00:00";
FRError->Lines->Clear();
FRError->Lines->Add("CRC错误的块");
return;
}
if (CMD=="FSFile") //发送方发来的是文件数据
{
if (WriteFile!=NULL) //有效的文件流
{
Cancel->Enabled=true;
try
{
if (WriteFile->Size<=FileData.Position) //当前块是文件尾(正常接收)
FRStatusBar->Panels->Items[1]->Text=FormatFloat("###,###,###",FileData.Position+FileData.Size)+"/"+FormatFloat("###,###,###",WriteFileSize);
else FRStatusBar->Panels->Items[1]->Text="纠错:"+IntToStr(FileData.Position);
while (WriteFile!=NULL && WriteFile->Size<FileData.Position) //如果当前块超过了文件尾
{
WriteFile->Seek(0,soFromEnd); //写无用数据到文件
WriteFile->WriteBuffer(FileData.Data,FileData.Size);
}
if (WriteFile==NULL) return ;
WriteFile->Seek(FileData.Position,soFromBeginning);//写当前文件块
WriteFile->WriteBuffer(FileData.Data,FileData.Size);
FRBlocks++;
}
catch (...)
{
FRStatusBar->Panels->Items[1]->Text="写文件错误!";
SendData_1("FRErr","",0); //向发送方发出写文件错误信息
}
}
return;
}
if (CMD=="FSStop") //发送方发来的是文件发送结束指令
{
if (WriteFile!=NULL) //文件有效
{
int Poss[250]; //需要重发的数据块
int k=0;
int j=0;
FRError->Lines->Add("**需要重发的块**");
while (j<WriteListCount-1) //搜索文件块数组
{
if (!WriteList[j]) //错误的文件块
{
if (k<250) //一次最多发250个错误的文件块信息
{
Poss[k]=j; //错误文件块编号数据
k++; //错误块计数器
}
FRError->Lines->Add(IntToStr(j*1000));
}
j++;
}
if (k>0) //有错误的文件块
{
SendData_1("FRRead",(char *)Poss,k*sizeof(int));//向发送发错误块数据
}
else //没有错误的数据块
{
delete WriteFile; //关闭文件
WriteFile=NULL;
FRBlocks=0;
delete [] WriteList; //删除文件状态标志数组
WriteListCount=0; //文件状态标志计数
SendData_1("FREnd","",0); //通知发送方文件传送完毕
Timer1->Enabled=false; //关闭文件传送计时器
FRStatusBar->Panels->Items[1]->Text="接收完毕!";
}
}
return;
}
if (CMD=="FSCanc") //发送方发来的是中断命令
{
try
{
FileName=FileData.Data; //取出文件文件名
delete WriteFile; //关闭文件
WriteFile=NULL;
DeleteFile(GetDir()+"\\"+FileName); //删除未接受完的文件
SendData_1("FRCanc","",0); //通知发送方已经中断
}
catch (...)
{
}
FRStatusBar->Panels->Items[1]->Text="发送方中断传输";
return;
}
//************************执行重发命令*******************************
if (CMD=="FRRepa") //接收方发来的重发命令
{
SendData_1("FSLast","",0); //执行发送方重发
return;
}
if (CMD=="FSRepa") //发送方发来的重发命令
{
SendData_1("FRLast","",0); //执行接收方重发
return;
}
//************************以下是发送方命令处理程序********************
if (CMD=="FRRate")
{
memmove(&Rate,FileData.Data,sizeof(float));
return;
}
if (CMD=="FRCRC") //接收方发来的是CRC校验错信息
{
SendFile_1(FileData.Position); //重发错误的文件块
FSRepa->Lines->Add(IntToStr(FileData.Position));
return;
}
if (CMD=="FRCanc") return; //接收方已经中断
if (CMD=="FRReje") //接收方发来拒绝接收指令
{
if (FSTimeOut>MaxTimeOut->Text.ToIntDef(60)) return; //超时
if (MessageDlg("对方拒绝接收,重试吗?",mtConfirmation,mbOKCancel,0)==mrOk)
{
SendData_1("FSLast","",0); //重试
return;
}
else CMD="FREnd"; //结束发送
}
if (CMD=="FRNot") //接收方发来文件无重名消息
{
if (FSTimeOut>MaxTimeOut->Text.ToIntDef(60)) return; //超时
StartSend(); //开始发送文件
return;
}
if (CMD=="FRExis") //接收方发来文件重名消息
{
if (!Cancel->Enabled) return; //已经Cancel
if (FSTimeOut>MaxTimeOut->Text.ToIntDef(60)) return; //超时
FileName=FileData.Data; //取出文件名,弹出对话框
if (MessageDlg(FileName+"\r\n同名的文件已经存在,覆盖吗?",mtConfirmation,mbOKCancel,0)==mrOk)
{
StartSend(); //开始发送文件
return;
}
else CMD="FREnd"; //用户选择"No",执行结束文件发送命令
}
if (CMD=="FRAll") //接收方发来的是传送文件命令
{
if (ReadFile!=NULL) //文件有效
{
if (ReadFile->Position>0) return;//文件已经开始传送
TimerCount=0; //文件传送计时器
FSBlocks=0;
Timer1->Enabled=true;
FSStatusBar->Panels->Items[2]->Text="00:00:00";
int Pos=0;
while (Pos<ReadFileSize&&ReadFile!=NULL)//循环发送文件块
{
try
{
if (!Cancel->Enabled) return;//用户按下了"取消"健
Pos+=SendFile_1(Pos); //发送文件块
if (Cancel->Enabled) FSStatusBar->Panels->Items[1]->Text=FormatFloat("###,###,###",Pos)+"/"+FormatFloat("###,###,###",ReadFileSize);
else FSTimer->Enabled=false;
}
catch (...)
{
FSStatusBar->Panels->Items[1]->Text="读文件错误!";
}
}
SendData_1("FSStop","",0); //通知接收方传送完毕
}
else
{
FSStatusBar->Panels->Items[1]->Text="文件未打开!";
}
return;
}
if (CMD=="FRRead") //发送方按接收方发来的块号传送文件块(用于纠错)
{
if (ReadFile!=NULL)
{
int Pos[250]; //文件块号数组
memmove(Pos,FileData.Data,FileData.Size);//取出接收方发来块号数据
int n=FileData.Size/sizeof(int);//要发的块数量
for (int j=0;j<n;j++)
{
try
{
if (!Cancel->Enabled) return;//用户按下了"取消"健
SendFile_1(Pos[j]*1000); //发送所需要的文件块
FSRepa->Lines->Add(IntToStr(Pos[j]*1000));
if (Cancel->Enabled) FSStatusBar->Panels->Items[1]->Text="重发:"+FormatFloat("###,###,###",Pos[j]*1000);
else FSTimer->Enabled=false;
}
catch (...)
{
FSStatusBar->Panels->Items[1]->Text="读文件错误!";
}
}
SendData_1("FSStop","",0); //通知接收方传输完毕
}
else
{
FSStatusBar->Panels->Items[1]->Text="文件未打开!";
}
return;
}
if (CMD=="FRErr") //接收方发来写错误消息
{
if (MessageDlg("接收方写文件失败!重试吗?",mtConfirmation,mbOKCancel,0)==mrOk)
{
SendData_1("FSLast","",0); //重发
return;
}
else CMD="FREnd"; //用户选择"No",执行结束文件发送命令
}
if (CMD=="FREnd") //接收方发来文件传输结束信息
{
if (ReadFile==NULL)
{
FSStatusBar->Panels->Items[1]->Text="停止发送!";
Sent->Enabled=false; //界面处理
Cancel->Enabled=false;
Add->Enabled=true;
Clear->Enabled=true;
SetUp->Enabled=true;
return;
}
delete ReadFile; //关闭文件
ReadFile=NULL;
Timer1->Enabled=false; //关闭文件传输计时器
ListView1->Items->Delete(0); //删掉已经发送的文件信息
FullFileName->Delete(0);
if (ListView1->Items->Count>0) //还有未发送的文件
{
FSRepa->Lines->Clear();
FRCMDS->Lines->Clear();
FileName=ExtractFileName(FullFileName->Strings[0]); //取出文件名
SendData_1("FSName",FileName.c_str(),FileName.Length()); //发送文件名信息
ListView1->ItemIndex=0;
}
else //文件已经全部发送完毕
{
Sent->Enabled=false; //界面处理
Cancel->Enabled=false;
Add->Enabled=true;
Clear->Enabled=true;
SetUp->Enabled=true;
}
FSStatusBar->Panels->Items[1]->Text="发送完毕!";
return;
}
}
void __fastcall TSendFiles::FormCreate(TObject *Sender)
{
Dir->Text=GetCurrentDir(); //初始路径(移植时要增加保存上次值的功能)
}
//---------------------------------------------------------------------------
void __fastcall TSendFiles::SentClick(TObject *Sender) //发送按钮
{
AnsiString FileName;
FileName=ExtractFileName(FullFileName->Strings[0]); //文件名
SendData_1("FSName",FileName.c_str(),FileName.Length()); //发送文件名信息
FSStatusBar->Panels->Items[1]->Text="";
FSStatusBar->Panels->Items[2]->Text="";
FSStatusBar->Panels->Items[3]->Text="";
ListView1->ItemIndex=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -