[Delphi/IndyFTP Client]Data connecties in TIME_WAIT

Pagina: 1
Acties:

  • Coltrui
  • Registratie: Maart 2001
  • Niet online
Ik heb een Delphi-applicatietje dat via FTP een aantal bestandjes van 60 bytes moet gaan downloaden van een FTP-server. Hiervoor gebruik ik de IndyFTP Client component waarbij de property Passive op True staat.
Ik creëer verder een StringList, waarin ik het resultaat van het listcommando op de FTPserver stockeer en ga die daarna aflopen om de bestanden met de Get procedure (al dan niet) te gaan downloaden.

Nu loopt dit prima, tot ik stresstest met een paar duizend bestanden op een FTP-servertje op het LAN.
De eerste twee- à driehonderd bestandjes vliegen binnen de paar seconden binnen, maar daarna moet ik wachten tot de server die twee- à driehonderd dataconnecties gesloten heeft die blijkbaar een paar minuten in TIME_WAIT status blijven staan.

Zie ik een FTP eigenschap over het hoofd? Is het te omzeilen dat er voor elk bestand een nieuwe data connection wordt gemaakt? Kan ik clientside met een bepaald commando in de OnAfterGet-event een close data connection forceren?

Alvast bedankt.

[ Voor 4% gewijzigd door Coltrui op 25-08-2006 15:21 ]


Verwijderd

Voor zover ik weet zie je niets over het hoofd. Het FTP RETR commando ondersteunt maar 1 file per keer, en TIdFTP.InternalGet (de routine die die RETR uitvoert) doet zoiets als:
Delphi:
1
2
3
4
5
6
Connect;
try
  // voer de RETR uit
finally
  Disconnect;
end;

DoAfterGet (waarin de OnAfterGet eventhandler wordt aangeroepen) komt pas hierna, en dan is er al gedisconnect.

  • Coltrui
  • Registratie: Maart 2001
  • Niet online
Dat is behoorlijk jammer dan, gezien dat zou willen zeggen dat je maximum rond de 250 files kan downloaden zonder zo'n lange tijd te moeten wachten. Ik zou eens moeten testen of dat 250/per client, of algemeen is, gezien dit tooltje door meerdere users concurrent gebruikt moet worden...

Overigens levert een testje met de WS FTP PRO-client identiek hetzelfde resultaat op - ook indien de download gedaan wordt op een remote FTP-server van mijn provider.

Misschien dat dit topic beter naar Netwerken verhuist?

Verwijderd

Geen idee of 't FTP protocol het toelaat, maar misschien zou je een eigen TIdFTP afgeleide kunnen maken die een GetMultipleFiles(AFileList: TStrings) method toevoegt?
Ik wou een voorbeeld hiervan maken, maar sinds vandaag geeft m'n Delphi IDE een access violation in "coreide60.bpl" wanneer ik een hoofdletter i probeer in te tikken. Niet handig wanneer je met Indy componenten probeert te werken. :(

Mijn idee was om TIdFTP.InternalGet als basis te nemen, en daar allereerst de dingen uit te slopen die je niet nodig hebt (het Passive = False stuk, en de Resume afhandeling), en dan
Delphi:
1
2
3
4
5
6
7
8
          Connect;
          try
            Self.WriteLn(ACommand);
            Self.GetResponse([125, 150, 154]); //APR: Ericsson Switch FTP
            ReadStream(ADest, -1, True);
          finally
            Disconnect;
          end;

te vervangen door iets als
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
          Connect;
          try
            for i := 0 to AFileList.Count - 1 do begin
              stream := TMemoryStream.Create;
              Self.WriteLn('RETR ' + AFileList[i]);
              Self.GetResponse([125, 150, 154]); //APR: Ericsson Switch FTP
              ReadStream(stream, -1, True);
              AFileList.Objects[i] := stream;
            end;  
          finally
            Disconnect;
          end;

Je hebt dan aan het eind in 't object van ieder AFileList item een stream staan met daarin de opgehaalde file, en daar kun je dan je ding mee doen (uitlezen, opslaan, etc.). Die streams daarna overigens wel netjes opruimen, anders heb je een prachtige memory leak. ;)
Binnen die loop zul je waarschijnlijk ook nog wel wat checks moeten doen die InternalGet aan het eind doet (GetResponse, DoStatus), maar dat kan ik nu helaas niet testen...

Voordeel van Indy is dat Chad Hower cs. de boel helemaal open hebben gemaakt, en je de source naar gelieven kunt aanpassen en uitbreiden.
Maar of mijn idee uberhaupt werkt weet ik niet. Misschien laat 't FTP protocol geen meerdere RETRs in 1 connectie toe?

Verwijderd

Interessant probleem! Ik heb me al vaker afgevraagd wat TIME_WAIT betekende en je topic heeft me gemotiveerd eens te gaan Googlen.

Dit artikel (eerste hit :w) legt het allemaal best duidelijk uit.

Conclusie: De TIME_WAIT toestand is een eigenschap van TCP/IP en zit dus op een heel andere laag dan je FTP programma. Je kan er vanuit je applicatie dus niet veel aan doen; behalve dan niet zoveel verbindingen openen, maar dat is met FTP niet echt te voorkomen.

De lengte van TIME_WAIT valt wel te tweaken in het register van een Windows PC (in een artikel dat op die pagina gelinkt wordt staat hoe). Let op dat dat alleen bij de server uithaalt; de kant die de verbinding als eerste sluit krijgt de TIME_WAIT, en bij FTP is dat altijd de server.

Als je overschakelt naar HTTP kun je zorgen dat de client de TIME_WAIT moet wachten en niet de server, als je een Content-Length meestuurt en als server een paar seconde wachten met het sluiten van de connectie om de client de kans te geven dat als eerste te doen.

Maar sowieso is het alleen een stress-test, toch? Hoe relevant is dit probleem in een productie set-up? Als het ontwerp van je systeem inhoudt dat je meer dan 300 files moet overblaffen in 4 minuten kun je denk ik beter naar een andere oplossing gaan zoeken.

  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

HTTP heeft iets als streaming van requests (meerdere achter elkaar in dezelfde verbinding/channel) misschien dat er met FTP ook zoiets kan?

Nu met Land Rover Series 3 en Defender 90


  • Depress
  • Registratie: Mei 2005
  • Laatst online: 12-02 13:20
Misschien dat je gewoon een pauze na 200 files van paar seconden kunt maken. En dat je als het waren de HTTP met rust laat, en zo die TIME_WAIT omzeilt?

Moet je wel met Threads gaan werken om je GUI te blijven gebruiken lijkt me, er van uit gaand dat je sleep() - (of hoe het in delphi heet, lang niet meer gebruikt) gebruikt.

[ Voor 36% gewijzigd door Depress op 26-08-2006 16:54 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 11:20
TIME_WAIT kun je beinvloeden door de linger settings aan te passen:

setsockopt( .... , SO_LINGER, ... )

[edit]

Oh ja, en SO_REUSEADDRES ook volgens mij ...

[ Voor 21% gewijzigd door farlane op 28-08-2006 08:58 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Coltrui
  • Registratie: Maart 2001
  • Niet online
Helder artikel, OneOfBorg, thanx :) Volgens dat artikel is het mijns inziens niet echt aan te raden om die TIME_WAIT te gaan tweaken, gezien de regel is dat 'hoe meer je het nodig hebt, hoe dieper je jezelf in de shit werkt als je die tijd gaat inkorten'.

Gezien die paar honderd bestandjes in principe ook in productieomgeving zouden moeten binnenvliegen, zal ik het inderdaad over een andere boeg moeten gooien. Aan het grote aantal bestanden kan ik jammer genoeg niets doen: die worden geleverd door derden.

HTTP is een optie, maar dan zit ik met de rompslomp van het bijhouden van een soort indexfile (en dan nog op de server van een third party), gezien een listing opvragen niet mogelijk is via HTTP. Misschien is de combinatie van FTP voor de listing en HTTP voor de download - eventueel in combinatie met een remote zip componentje - een mogelijkheid... Niet netjes, maar goed.


Edit: @Afterlife: het crappy FTP-protocol opent blijkbaar altijd per file een nieuwe connectie. Ik las dat MGET bijvoorbeeld ook voor elk bestand een nieuw channel aanmaakt, wat niet logisch zou zijn indien FTP het toe zou laten om meerdere gets per connection te doen. In ieder geval bedankt voor het meedenken :)

[ Voor 14% gewijzigd door Coltrui op 28-08-2006 15:52 ]

Pagina: 1