客户端
procedure TfrmClient.btnSaveClick(Sender: TObject);
var
cmd:String; //服务器通信命令
ASize,TotalSize:Int64;//缓冲区大小,文件流大小
AFileStream:TFileStream;//文件流变量
begin
IdTCPClient1.Host:=Edit1.Text;
IdTCPClient1.Port:=StrToIntDef(Edit2.Text,9225);
IdTCPClient1.Connect;
Try
IdTCPClient1.IOHandler.WriteLn('BEGIN');//提示客户端开始接收
cmd:=IdTCPClient1.IoHandler.ReadLn;
//以'|'分离文件名
dlgSave.FileName:=Copy(cmd,Pos('|',cmd)+1,Length(cmd));
if not dlgSave.Execute then
begin
IdTCPClient1.IOHandler.WriteLn('CANCEL');//告诉服务器取消
IdTCPClient1.Disconnect;
Exit;
end;
//分离文件大小
TotalSize:=StrToInt(Copy(cmd,0,Pos('|',cmd)-1));
//建立文件流准备接收
AFileStream:=TFileStream.Create(dlgSave.FileName,fmCreate);
try //开始循环接受
Repeat
IdTCPClient1.IOHandler.Writeln(IntToStr(AFileStream.Size));//发送当前传输的位置
ASize:=Min(TotalSize-AFileStream.Size,IdTCPClient1.IOHandler.RecvBufferSize);
//选择剩余大小和缓冲区大小小的一个作为传输的大小
IdTCPClient1.IOHandler.ReadStream(AFileStream,ASize);//接收流
StatusBar1.Panels[1].Text:=Format('当前传输位置%d/大小%d',[AFileStream.Size,TotalSize]);
Application.ProcessMessages;
Until AFileStream.Size=TotalSize; //当大小一致时退出循环
finally
AFileStream.Free;//释放文件流
end;
IdTCPClient1.IOHandler.WriteLn('END');//告诉服务器已经接收完毕
StatusBar1.Panels[1].Text:='传输文件成功';
except
StatusBar1.Panels[1].Text:= '连接服务器失败或者对方已经中断传输!';
End;
IdTCPClient1.Disconnect; //断开连接
end;
服务端
unit PasServer;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdContext, IdBaseComponent, IdComponent, IdCustomTCPServer,
IdTCPServer, StdCtrls, ComCtrls,Math;
type
TfrmServer = class(TForm)
Label1: TLabel;
Edit1: TEdit;
btnStart: TButton;
btnExit: TButton;
btnOpen: TButton;
IdTCPServer1: TIdTCPServer;
OpenDialog1: TOpenDialog;
Label2: TLabel;
Edit2: TEdit;
Label3: TLabel;
Edit3: TEdit;
StatusBar1: TStatusBar;
ProgressBar1: TProgressBar;
btnCancel: TButton;
procedure btnOpenClick(Sender: TObject);
procedure btnExitClick(Sender: TObject);
procedure btnStartClick(Sender: TObject);
procedure IdTCPServer1Connect(AContext: TIdContext);
procedure IdTCPServer1Execute(AContext: TIdContext);
procedure FormCreate(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
private
{ Private declarations }
AFileStream:TFileStream;
procedure ButtonBegin;
procedure ButtonEnd;
public
{ Public declarations }
end;
var
frmServer: TfrmServer;
implementation
{$R *.dfm}
procedure TfrmServer.ButtonBegin;
begin //VCL开始状态设置
btnStart.Enabled:=False;
btnExit.Enabled:=False;
btnCancel.Enabled:=True;
btnOpen.Enabled:=False;
end;
procedure TfrmServer.ButtonEnd;
begin //VCL结束状态设置
btnStart.Enabled:=True;
btnExit.Enabled:=True;
btnCancel.Enabled:=False;
btnOpen.Enabled:=True;
end;
procedure TfrmServer.btnStartClick(Sender: TObject);
begin
if not FileExists(Edit1.Text) then //检测文件是否存在
begin
ShowMessage('文件不存在,请重新选择!!!');
exit;
end;
//建立文件流
AFileStream:=TFileStream.Create(Edit1.Text,fmOpenRead);
ProgressBar1.Max:=AFileStream.Size;
ProgressBar1.Position:=0;
ButtonBegin;//VCL开始状态设置
//服务器准备好连接
IdTCPServer1.DefaultPort:=StrToIntDef(Edit2.Text,9225);
if not IdTCPServer1.Active then IdTCPServer1.Active:=True;
end;
procedure TfrmServer.btnCancelClick(Sender: TObject);
begin
StatusBar1.Panels[1].Text:='传输取消.....';
AFileStream.Free; //释放文件流
ButtonEnd; //VCL结束状态设置
end;
procedure TfrmServer.btnExitClick(Sender: TObject);
begin
if IdTCPServer1.Active then
IdTCPServer1.Active:=False;
Close;
end;
procedure TfrmServer.btnOpenClick(Sender: TObject);
begin
OpenDialog1.Execute;
if OpenDialog1.FileName<>'' then
begin
Edit1.Text:=OpenDialog1.FileName;
btnStart.Enabled:=True;
end;
end;
procedure TfrmServer.FormCreate(Sender: TObject);
begin
StatusBar1.Panels[1].Text:='文件传输服务器V1.1';
btnStart.Enabled:=False;
btnCancel.Enabled:=False;
end;
procedure TfrmServer.IdTCPServer1Connect(AContext: TIdContext);
begin
Edit3.Text:=AContext.Binding.IP;
end;
procedure TfrmServer.IdTCPServer1Execute(AContext: TIdContext);
var
cmd:string; //客户端命令信息
ASize:Integer; //需要的传输流大小
begin
with AContext.Connection do //已经连街上的一个进程
begin
cmd:=UpperCase(IoHandler.ReadLn); //客户端发送的命令字符串
if cmd='BEGIN' then //开始传输....
begin
//告诉客户机文件大小及文件名
IoHandler.WriteLn(Format('%d|%s',[AFileStream.Size,ExtractFileName(Edit1.Text)]));
StatusBar1.Panels[1].Text:='准备传输......';
exit;
end;
if cmd='CANCEL' then //中止传输
begin
StatusBar1.Panels[1].Text:='客户中止传输....';
//保持传输状态
Exit;
end;
if cmd='END' then
begin
//文件传输完毕
btnCancel.Click;
StatusBar1.Panels[1].Text:='文件传输已经完成...';
Exit;
end;
//按照指定位置传输文件
AFileStream.Seek(StrToInt(cmd),soFromBeginning);//转到文件的传输位置
ASize:=Min(AFileStream.Size-AFileStream.Position,IoHandler.RecvBufferSize);
//计算需要发送大小,Min()函数在Math单元
//IoHandler.WriteBufferOpen;//准备发送缓冲
IoHandler.Write(AFileStream,Asize);
//IoHandler.WriteBufferClose;
StatusBar1.Panels[1].Text:=Format('当前文件传输位置%s/大小%d',[cmd,AFileStream.Size]);
ProgressBar1.Position:=ProgressBar1.Position+ASize;
end;
end;
end.