На скрінлисту відображені перехвачені пакети за допомоги Wireshark, при копіюванні файла с одного FTP сервера на другий FTP, використовуючи TotalCommander як FTP клієнт.
Модифікуючи приклад(OverbyteIcsFtpThrd.dproj) FTP клієнта з бібліотеки (ICS), пробуємо змоделювати передачу файла між двома FTP серверами.
... TTransferThread = class(TThread) private FMsg : String; FtpClient119 : TFtpClient; FtpClient116 : TFtpClient; public constructor CreateThread; procedure AddToListBox; procedure Display(Msg: String); procedure CliDisplay(Sender: TObject; var Msg: String); procedure FtpClient119RequestDone( Sender : TObject; RqType : TFtpRequest; ErrCode : Word); procedure FtpClient116RequestDone( Sender : TObject; RqType : TFtpRequest; ErrCode : Word); procedure Execute ; override; end; ... constructor TTransferThread.CreateThread; begin FreeOnTerminate := TRUE; inherited Create(FALSE); end; procedure TTransferThread.Execute; var RawCmd: AnsiString; { AG V7.02 We do not need RawByteString here } i:integer; begin FtpClient119 := TFtpClient.Create(nil); FtpClient119.OnDisplay := CliDisplay; FtpClient119.OnProgress64 := nil; FtpClient119.OnRequestDone := FtpClient119RequestDone; FtpClient119.OnSessionConnected := nil; FtpClient119.OnSessionClosed := nil; FtpClient119.OnStateChange := nil; FtpClient119.Multithreaded := TRUE; FtpClient119.Timeout := 60; // default is 15 FtpClient119.HostName := '10.10.1.119'; FtpClient119.Port := 'ftp'; FtpClient119.UserName := 'user'; FtpClient119.Password := 'pass'; FtpClient119.DisplayFileFlag := TRUE; FtpClient119.LocalFileName := ''; FtpClient119.HostDirName := '/online/P1002249/'; FtpClient119.HostFileName := 'P1002249.mov'; FtpClient116 := TFtpClient.Create(nil); FtpClient116.OnDisplay := CliDisplay; FtpClient116.OnProgress64 := nil; FtpClient116.OnRequestDone := FtpClient116RequestDone; FtpClient116.OnSessionConnected := nil; FtpClient116.OnSessionClosed := nil; FtpClient116.OnStateChange := nil; FtpClient116.Multithreaded := TRUE; FtpClient116.Timeout := 60; // default is 15 FtpClient116.HostName := '10.10.1.116'; FtpClient116.Port := 'ftp'; FtpClient116.UserName := 'user'; FtpClient116.Password := 'pass'; FtpClient116.DisplayFileFlag := TRUE; FtpClient116.LocalFileName := ''; FtpClient116.HostDirName := '/'; FtpClient116.HostFileName := 'P1002249.mov'; if not FtpClient119.Connect then begin Display('Connect1 failed'); FtpClient119.Abort; Exit; end; if not FtpClient116.Connect then begin Display('Connect2 failed'); FtpClient119.Abort; Exit; end; sleep(1000); if not FtpClient119.Feat then begin Display('feat failed'); FtpClient119.Abort; Exit; end; sleep(1000); if not FtpClient116.Feat then begin Display('feat failed'); FtpClient119.Abort; Exit; end; sleep(1000); if not FtpClient119.Cwd then begin Display('CWD1 failed'); FtpClient119.Abort; Exit; end; sleep(1000); if not FtpClient116.Cwd then begin Display('CWD2 failed'); FtpClient119.Abort; Exit; end; sleep(1000); if not FtpClient119.Pwd then begin Display('PWD1 failed'); FtpClient119.Abort; Exit; end; sleep(1000); if not FtpClient116.Pwd then begin Display('PWD2 failed'); FtpClient119.Abort; Exit; end; sleep(1000); if not FtpClient119.Size then begin Display('SIZE failed'); FtpClient119.Abort; Exit; end; sleep(1000); if not FtpClient119.TypeBinary then begin Display('TYPE2 failed'); FtpClient119.Abort; Exit; end; sleep(1000); if not FtpClient116.TypeBinary then begin Display('TYPE2 failed'); FtpClient119.Abort; Exit; end; sleep(1000); if not FtpClient116.PASV then begin Display('PASV failed'); FtpClient119.Abort; Exit; end; for I := 0 to 20 do begin sleep(50); application.ProcessMessages; end; if not FtpClient119.RETR then begin Display('RETR failed'); FtpClient119.Abort; Exit; end; if not FtpClient116.STOR then begin Display('STOR failed'); FtpClient116.Abort; Exit; end; end; procedure TTransferThread.FtpClient116RequestDone( Sender : TObject; RqType : TFtpRequest; ErrCode : Word); var test,test1:string; RawCmd: AnsiString; i:integer; data:boolean; begin Display('Request ' + LookupFTPReq (RqType) + ' Done.'); Display('StatusCode = ' + IntToStr((Sender as TFtpClient).StatusCode)); Display('LastResponse was : ''' + (Sender as TFtpClient).LastResponse + ''''); case RqType of ftpSizeAsync : Display( 'File size is ' + ' bytes' ); ftpPASVAsync: begin test:=''; for I := 1 to Length(FtpClient116.LastResponse) do begin if FtpClient116.LastResponse[i]=')' then data:=false; if data then test:=test+FtpClient116.LastResponse[i]; if FtpClient116.LastResponse[i]='(' then data:=true; end; Display(test); Display( 'PASV is ' +(Sender as TFtpClient).PASVResult+ ' bytes' ); RawCmd:='PORT '+test; if FtpClient119.ControlSocket.State = wsConnected then FtpClient119.ExecAsync(ftpPortAsync, RawCmd, [200, 227], nil); end; ftpXDSizeAsync : Display('XD File size is ' + IntToStr((Sender as TFtpClient).XDSizeResult)+' bytes' ); end; end; procedure TTransferThread.FtpClient119RequestDone( Sender : TObject; RqType : TFtpRequest; ErrCode : Word); var RawCmd: AnsiString; begin Display('Request ' + LookupFTPReq (RqType) + ' Done.'); Display('StatusCode = ' + IntToStr((Sender as TFtpClient).StatusCode)); Display('LastResponse was : ''' + (Sender as TFtpClient).LastResponse + ''''); case RqType of ftpSizeAsync : Display( 'File size is ' + ' bytes' ); ftpXDSizeAsync : Display( 'XD File size is ' + ' bytes' ); end; end;
Links:
1) http://wiki.overbyte.be/wiki/index.php/Main_Page - ICS is a free internet component library.
2) http://www.wireshark.org/ - is the world's foremost network protocol analyzer.