На скрінлисту відображені перехвачені пакети за допомоги 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.
