Connection closed gracefully 问题

zhuozi_467 2010-07-06 08:22:55
参考了一些网络上关于文件传输的资料,用IdTCPClient1,IdTCPSever写了一个传输文件的程序,在传输过程中传输端有时会爆“ Connection closed gracefully”或“Socket Error #10054 Connection reset by peer.”错误,出现后者情况时,一般是在接收端自动关闭(没有报异常),这是一端被强制关闭造成的,查了一天也找不出源头。搞得很郁闷。。
现把程序列出来,哪个高手帮忙分析下,到底是哪出问题了。。。

传输端:
Procedure TMainForm.SendFile(pFilePath:String);
var
dir,sFile,lCmd:String;
Rdir:Stringarray;
fSize,iFileType,iFileIndex,i:integer;
lFileSize,ASize:Int64;
lFileSendSize:integer;
begin

TmSendDBFile.Enabled := False;
try
PClient := Tidtcpclient.Create(nil);
PClient.Host := F_RemoteServerIP;//'192.168.0.20';//fip;
PClient.Port := 9923;
sleep(3000);
PClient.Connect();

if PClient.Connected then
begin
PClient.WriteLn('START'); //通知客户端开始传输
PClient.WriteLn(IntToStr(F_DBUpdateFileCount)); //DB文件个数
PClient.WriteLn(IntToStr(F_MediaUpdateFileCount)); //Media文件个数

iFileType := StrToInt(PClient.ReadLn()); //接收要发送的文件类型
//发送DB文件
if iFileType = 0 then
begin
repeat
i:=0;
iFileIndex := StrToInt(PClient.ReadLn()); //接收要发送的文件索引
F_FileName := F_DBUpdateFile[iFileIndex].sFile;
PClient.WriteLn(F_FileName);
sFile := ExtractFilePath(Application.ExeName) + 'db\' + F_FileName;
red_NetUpdate.Lines.Append('['+TimetoStr(Now())+'] 发送文件:'+sFile);
F_FileStream := TFileStream.Create(sFile,fmopenread);
lFileSize := F_FileStream.Size;
PClient.writeln(IntToStr(lFileSize));

lFileSendSize := StrToInt(PClient.ReadLn); //客户端发送的命令字符串
while lFileSendSize<=lFileSize do
begin
if FSendAgainFlag then
begin
//取已接收文件流的大小
if i<>0 then ////////////////报“Socket Error #10054 Connection reset by peer”//////////////
lFileSendSize := StrToInt(PClient.ReadLn);

//当cmd返回0时,表示文件接收完毕,退出循环
if (lFileSendSize=0) and (i<>0) then
break;
//按照指定位置传输文件
F_FileStream.Seek(lFileSendSize, soFromBeginning);
//转到文件流传输的位置
ASize := Min(F_FileStream.Size - F_FileStream.Position, PClient.RecvBufferSize);
//计算需要发送的大小,Min()函数在Math单元
PClient.OpenWriteBuffer; //准备发送缓冲
PClient.WriteStream(F_FileStream, false, false, ASize);
//显示进度条
if F_FileStream.Size<>0 then
pb_Progress.Position := F_FileStream.Position * 100 div F_FileStream.Size
else
pb_Progress.Position := 0;
lbl_FileName.Visible := True;
pb_Progress.Visible := True;

PClient.CloseWriteBuffer; //结束发送缓冲
inc(i);
end;
end;
FSendDBCount := FSendDBCount+1;
F_FileStream.Free;
red_NetUpdate.Lines.Append('['+TimetoStr(Now())+'] 文件:'+sFile+',发送完成!');
until F_DBUpdateFileCount = FSendDBCount;
end;

if F_MediaUpdateFileCOunt = 0 then
red_NetUpdate.Lines.Append('无多媒体传输文件,请确认!')
else
//发送media文件
repeat
i:=0;
iFileIndex := StrToInt(PClient.ReadLn()); //接收要发送的文件索引
F_FileName := F_MediaUpdateFile[iFileIndex].sFile;

PClient.WriteLn(F_FileName);
sFile := ExtractFilePath(Application.ExeName) + 'media\' + F_FileName;
red_NetUpdate.Lines.Append('['+TimetoStr(Now())+'] 发送文件:'+sFile);
F_FileStream := TFileStream.Create(sFile,fmopenread);
lFileSize := F_FileStream.Size;

PClient.writeln(IntToStr(lFileSize)); //传输文件大小

lFileSendSize := StrToInt(PClient.ReadLn); //客户端发送的命令字符串
while lFileSendSize<=lFileSize do
begin
if FSendAgainFlag then
begin
//取已接收文件流的大小
if i<>0 then
begin
try
lFileSendSize := StrToInt(PClient.ReadLn);
except
Showmessage('123');
end;
end;
//当cmd返回0时,表示文件接收完毕,退出循环
if (lFileSendSize=0) and (i<>0) then
break;
//按照指定位置传输文件
F_FileStream.Seek(lFileSendSize, soFromBeginning);
//转到文件流传输的位置
ASize := Min(F_FileStream.Size - F_FileStream.Position, PClient.RecvBufferSize);
//计算需要发送的大小,Min()函数在Math单元
PClient.OpenWriteBuffer; //准备发送缓冲
PClient.WriteStream(F_FileStream, false, false, ASize);
//显示进度条
if F_FileStream.Size<>0 then
pb_Progress.Position := F_FileStream.Position * 100 div F_FileStream.Size
else
pb_Progress.Position := 0;
lbl_FileName.Visible := True;
pb_Progress.Visible := True;

PClient.CloseWriteBuffer; //结束发送缓冲
inc(i);
end;
end;
FSendMediaCount := FSendMediaCount+1;
F_FileStream.Free;
red_NetUpdate.Lines.Append('['+TimetoStr(Now())+'] 文件:'+sFile+',发送完成!');
until F_MediaUpdateFileCOunt = FSendMediaCount;

//接到END表示结束文件传输
if PClient.ReadLn='END' then
begin
//showmessage('模块升级1');
PClient.DisconnectSocket;
end;
red_NetUpdate.Lines.Add('★★★'+TimetoStr(Now())+' 文件发送完毕!★★★');
end;
finally
//showmessage('模块升级2');
PClient.DisconnectSocket;
PClient.Free;
end;
end;

接收端:
procedure TMainForm.PServerExecute(AThread: TIdPeerThread);
var
cmd,targetname:string;
lsize:int64;
fs:tfilestream;
ASize:int64;
iFileIndex,iFileType:integer;
begin
with athread.Connection do
begin
cmd:=trim(readln);
if cmd='START'then
begin
FRevDBCount := StrToInt(readln); //要接收DB文件个数
FRevMediaCount := StrToInt(readln); //要接收meidia文件个数 ,
//接收db文件
Repeat
if FDbCount = 0 then
begin
iFileIndex := 0;
iFileType := 0;
writeln(IntToStr(iFileType)); //发送文件类型
end
else
iFileIndex := iFileIndex+1;

writeln(IntToStr(iFileIndex)); //发送文件索引
targetname := FDBFilePath+readln;
//lbl_FileName.Caption :='正在接收文件:'+ targetname;
lSize := StrToIntDef(readln,0); //接收文件大小
try //循环开始接受
//建立文件流准备接收
fs := TFileStream.Create(targetname, fmCreate);
repeat
WriteLn(IntToStr(fs.Size));//发送当前传输的位置
ASize := Min(lsize - fs.Size, RecvBufferSize);
//选择剩余大小和缓冲区大小小的一个作为传输的大小
ReadStream(fs, ASize); //接收流
lbl_Progress.Caption :='当前传输位置'+ IntToStr(fs.Size) + '/大小' + IntToStr(lsize);
Application.ProcessMessages;
until fs.Size = lsize; //大小一致了表示结束
FDbCount := FDbCount+1 ;
WriteLn('0');//写‘0’表示告知客户端上一文件已经接收完毕
finally
fs.Free; //释放文件流
end;
until FRevDBCount = FDbCount;
//接收media文件
Repeat
if FMediaCount = 0 then
begin
iFileIndex := 0;
//iFileType := 0;
//writeln(IntToStr(iFileType)); //发送文件类型
end
else
iFileIndex := iFileIndex+1;

writeln(IntToStr(iFileIndex)); //发送文件索引
targetname := FMediaFilePath+readln;
lSize := StrToIntDef(readln,0); //接收文件大小
try //循环开始接受
//建立文件流准备接收
fs := TFileStream.Create(targetname, fmCreate);
repeat
WriteLn(IntToStr(fs.Size));//发送当前传输的位置
mmo_Report.Lines.Append(IntToStr(fs.Size));
ASize := Min(lsize - fs.Size, RecvBufferSize);
//选择剩余大小和缓冲区大小小的一个作为传输的大小
ReadStream(fs, ASize); //接收流
lbl_Progress.Caption :='当前传输位置'+ IntToStr(fs.Size) + '/大小' + IntToStr(lsize);
Application.ProcessMessages;
until fs.Size = lsize; //大小一致了表示结束
FMediaCount := FMediaCount+1 ;
WriteLn('0');//写‘0’表示告知客户端上一文件已经接收完毕
finally
fs.Free; //释放文件流
end;
until FRevMediaCount = FMediaCount;

writeln('END');
lbl_Progress.Caption :='当前传输位置'+ IntToStr(0) + '/大小' + IntToStr(0);
lbl_FileName.Caption :='文件接收完毕!';
//UpdateDB;
//EndRun(DEF_ALARM_END) ;
if FRevMediaCount+FRevDBCount = FMediaCount+ FDbCount then
disconnect;
end;
end;

end;
...全文
1149 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧