程序是根据别人的示例自已修改完成的,运行他的文件传输程序没出错,但自已写的这个在传完文件以后,服务器端会出现“线程超时”、作些修改会出现关闭窗口时出现“无效窗口句柄”之类的错误,我对这方面完成是菜鸟,整了很久就是找不到原因,望高手们指点指点
以下是部分主要代码:
// S_P2P 为TIdTcpServer,C_P2P为TIdTcpClient,它们放在同一程序中
// 文件流在双方同意传输后建立procedure TfrmNowChat.S_P2PExecute(AThread: TIdPeerThread);
var
cmd: string; //接收到客户端的字符串信息
ASize: Integer; //需要传输的流大小
begin
with AThread.Connection do //已经连街上的一个进程
begin
cmd := UpperCase(ReadLn); //客户端发送的命令字符串
if cmd = 'BEGIN' then //开始传输
begin
//告诉远程传输文件的大小和文件名
WriteLn(Format('%d|%s', [F_AFileStream.Size, ExtractFileName(FTranFile.FileName)]));
labProsStat.Caption := '准备传输...';
labDoingStat.Visible := true ;
bsSkinGauge1.Visible := true ;
Exit;
end;
if cmd = 'END' then //传输完成
begin
labProsStat.Caption := '已完成';
TsCancle ; // 重置相关变量
Exit;
end;
if cmd = 'CANCEL' then //传输取消
begin
//保持传输状态
labProsStat.Caption := '对方取消!';
TsCancle ;
Exit;
end; //按照指定位置传输文件
F_AFileStream.Seek(StrToInT(cmd), soFromBeginning); //转到文件流传输的位置
ASize := Min(F_AFileStream.Size - F_AFileStream.Position, RecvBufferSize);
//计算需要发送的大小,Min()函数在Math单元
OpenWriteBuffer; //准备发送缓冲
WriteStream(F_AFileStream, false, false, ASize);
//注意这个函数的参数。
CloseWriteBuffer; //结束发送缓冲 //StatusBar1.SimpleText := Format('当前传输位置%s/大小%d', [cmd, F_AFileStream.Size]);
labDoingStat.Caption := Format('%s/%d', [cmd, F_AFileStream.Size]);
bsSkinGauge1.Value := bsSkinGauge1.Value +ASize;
Application.ProcessMessages;
end;
end;procedure TfrmNowChat.C_AcceptTranFile ;
var
cmd: string;
ASize, TotalSize: Int64;
AFileStream: TFileStream;
begin
C_P2P.Host :=FTranFile.IP ; //连接主机
C_P2P.Port := 9925 ; //端口
C_P2P.Connect; //连接
try
C_P2P.WriteLn('BEGIN'); //提示服务器开始接收
cmd := C_P2P.ReadLn;
//以"|"符号分离文件名 SaveDialog1.FileName := Copy(cmd, Pos('|', cmd) + 1, Length(cmd));
savedialog1.Filter := ExtractFileExt(SaveDialog1.FileName)+'文件|*'+ExtractFileExt(SaveDialog1.FileName);
// showmessage(SaveDialog1.FileName);
if not SaveDialog1.Execute then
begin
C_P2P.WriteLn('CANCEL'); //告诉服务器取消
C_P2P.Disconnect; //断开连接
exit;
end; labDoingStat.Visible := true ;
bsSkinGauge1.Visible := true ;
labProsStat.Caption :='正在接收文件...' ; TotalSize := StrToInt(Copy(cmd, 0, Pos('|', cmd) - 1)); //分离文件大小
bsSkinGauge1.MaxValue := TotalSize ;
bsSkinGauge1.Value := 0 ; //建立文件流准备接收
AFileStream := TFileStream.Create(SaveDialog1.FileName, fmCreate);
try //循环开始接受
repeat
C_P2P.WriteLn(IntToStr(AFileStream.Size));//发送当前传输的位置
ASize := Min(TotalSize - AFileStream.Size, C_P2P.RecvBufferSize);
//选择剩余大小和缓冲区大小小的一个作为传输的大小
C_P2P.ReadStream(AFileStream, ASize); //接收流
bsSkinGauge1.Value := bsSkinGauge1.Value + ASize ; labDoingStat.Caption := Format('%d/%d', [AFileStream.Size, TotalSize]);
Application.ProcessMessages;
until AFileStream.Size = TotalSize; //大小一致了表示结束
finally
AFileStream.Free; //释放文件流
end;
C_P2P.WriteLn('END'); //提示服务器传输完成
labProsStat.Caption := '接收完成!';
bt1.Caption := '打开' ;
FTranFile.SaveFileName := SaveDialog1.FileName ;
TsCancle ;
bt1.Visible := true ;
labSel.Visible := true ;
except
labProsStat.Caption := '接收失败!';
TsCancle ;
end;
C_P2P.Disconnect;
end;procedure TfrmNowChat.TsCancle ; // 清除相关变量
begin
// 取消传输,无论在未连接或是已连接的状态下
InitFtranFile ;
labSel.Visible := false ;
bt1.Visible := false ;
bt2.Visible := false ;
labDoingStat.Visible := false ;
bsSkinGauge1.Visible := false ; F_AFileStream.Free; //释放文件流 if C_P2P.Connected then
C_P2P.Disconnect ;
if S_P2P.Active then
S_P2P.Active := false ; // 此句代码是想在传完后关闭服务器,以准备传其它文件,可是似乎会出错,我曾考虑过是不是应该在客户端断开连接后才关闭,将此句放在Disconnect中也会出错
end;
以下是部分主要代码:
// S_P2P 为TIdTcpServer,C_P2P为TIdTcpClient,它们放在同一程序中
// 文件流在双方同意传输后建立procedure TfrmNowChat.S_P2PExecute(AThread: TIdPeerThread);
var
cmd: string; //接收到客户端的字符串信息
ASize: Integer; //需要传输的流大小
begin
with AThread.Connection do //已经连街上的一个进程
begin
cmd := UpperCase(ReadLn); //客户端发送的命令字符串
if cmd = 'BEGIN' then //开始传输
begin
//告诉远程传输文件的大小和文件名
WriteLn(Format('%d|%s', [F_AFileStream.Size, ExtractFileName(FTranFile.FileName)]));
labProsStat.Caption := '准备传输...';
labDoingStat.Visible := true ;
bsSkinGauge1.Visible := true ;
Exit;
end;
if cmd = 'END' then //传输完成
begin
labProsStat.Caption := '已完成';
TsCancle ; // 重置相关变量
Exit;
end;
if cmd = 'CANCEL' then //传输取消
begin
//保持传输状态
labProsStat.Caption := '对方取消!';
TsCancle ;
Exit;
end; //按照指定位置传输文件
F_AFileStream.Seek(StrToInT(cmd), soFromBeginning); //转到文件流传输的位置
ASize := Min(F_AFileStream.Size - F_AFileStream.Position, RecvBufferSize);
//计算需要发送的大小,Min()函数在Math单元
OpenWriteBuffer; //准备发送缓冲
WriteStream(F_AFileStream, false, false, ASize);
//注意这个函数的参数。
CloseWriteBuffer; //结束发送缓冲 //StatusBar1.SimpleText := Format('当前传输位置%s/大小%d', [cmd, F_AFileStream.Size]);
labDoingStat.Caption := Format('%s/%d', [cmd, F_AFileStream.Size]);
bsSkinGauge1.Value := bsSkinGauge1.Value +ASize;
Application.ProcessMessages;
end;
end;procedure TfrmNowChat.C_AcceptTranFile ;
var
cmd: string;
ASize, TotalSize: Int64;
AFileStream: TFileStream;
begin
C_P2P.Host :=FTranFile.IP ; //连接主机
C_P2P.Port := 9925 ; //端口
C_P2P.Connect; //连接
try
C_P2P.WriteLn('BEGIN'); //提示服务器开始接收
cmd := C_P2P.ReadLn;
//以"|"符号分离文件名 SaveDialog1.FileName := Copy(cmd, Pos('|', cmd) + 1, Length(cmd));
savedialog1.Filter := ExtractFileExt(SaveDialog1.FileName)+'文件|*'+ExtractFileExt(SaveDialog1.FileName);
// showmessage(SaveDialog1.FileName);
if not SaveDialog1.Execute then
begin
C_P2P.WriteLn('CANCEL'); //告诉服务器取消
C_P2P.Disconnect; //断开连接
exit;
end; labDoingStat.Visible := true ;
bsSkinGauge1.Visible := true ;
labProsStat.Caption :='正在接收文件...' ; TotalSize := StrToInt(Copy(cmd, 0, Pos('|', cmd) - 1)); //分离文件大小
bsSkinGauge1.MaxValue := TotalSize ;
bsSkinGauge1.Value := 0 ; //建立文件流准备接收
AFileStream := TFileStream.Create(SaveDialog1.FileName, fmCreate);
try //循环开始接受
repeat
C_P2P.WriteLn(IntToStr(AFileStream.Size));//发送当前传输的位置
ASize := Min(TotalSize - AFileStream.Size, C_P2P.RecvBufferSize);
//选择剩余大小和缓冲区大小小的一个作为传输的大小
C_P2P.ReadStream(AFileStream, ASize); //接收流
bsSkinGauge1.Value := bsSkinGauge1.Value + ASize ; labDoingStat.Caption := Format('%d/%d', [AFileStream.Size, TotalSize]);
Application.ProcessMessages;
until AFileStream.Size = TotalSize; //大小一致了表示结束
finally
AFileStream.Free; //释放文件流
end;
C_P2P.WriteLn('END'); //提示服务器传输完成
labProsStat.Caption := '接收完成!';
bt1.Caption := '打开' ;
FTranFile.SaveFileName := SaveDialog1.FileName ;
TsCancle ;
bt1.Visible := true ;
labSel.Visible := true ;
except
labProsStat.Caption := '接收失败!';
TsCancle ;
end;
C_P2P.Disconnect;
end;procedure TfrmNowChat.TsCancle ; // 清除相关变量
begin
// 取消传输,无论在未连接或是已连接的状态下
InitFtranFile ;
labSel.Visible := false ;
bt1.Visible := false ;
bt2.Visible := false ;
labDoingStat.Visible := false ;
bsSkinGauge1.Visible := false ; F_AFileStream.Free; //释放文件流 if C_P2P.Connected then
C_P2P.Disconnect ;
if S_P2P.Active then
S_P2P.Active := false ; // 此句代码是想在传完后关闭服务器,以准备传其它文件,可是似乎会出错,我曾考虑过是不是应该在客户端断开连接后才关闭,将此句放在Disconnect中也会出错
end;
if cmd = 'CANCEL' then //传输取消
begin
//保持传输状态
labProsStat.Caption := '对方取消!';
TsCancle ;
AThread.Stop;///<-------添加这一行终止服务线程
Exit;
end;