客户端
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;interfaceuses 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.