Entwickler-Ecke
Internet / Netzwerk - TIdFTP mit IPv6
middel86 - Di 07.08.12 15:54
Titel: TIdFTP mit IPv6
Hallo,
Ich versuche gerade mit Hilfe der TIdFTP Komponente (Version 10 in Delphi 2010) eine Verbindung über IPv6 zu einem FTP Server zu erstellen, um dann eine Datei zu transferieren. Das connecten scheint auch zu funktionieren, will ich dann aber eine Datei vom Server herunter- oder heraufladen bekomme ich im Passive Mode folgende Exception:
| Zitat: |
| "You are connected using Ipv6. PASV is only for Ipv4. You have to use the EPSV command instead." |
Setze ich den Passive Mode auf False erhalte ich eine andere Exception:
| Zitat: |
| „“FE80:0:0:0:xxxx:xxxx:xxxx:xxxx“ is not a valid integer value“ |
Als FTP-Server verwende ich FileZilla (Version 0.9.41) welcher auf Port 21 hört. Habe es aber auch schon erfolglos mit anderen Ports versucht. Firewalls sind auch nicht aktiv.
Wenn ich das gleiche mit einem bestehenden FTP-Client veruche (z.B. FileZilla oder Total Commander) funktioniert der Datentransfer problemlos, sowohl im aktiv wie im passiv modus für GET und PUT.
Hier mein Code:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55:
| try FIdFTP := TIdFTP.Create(nil); FURL := TIdURI.Create();
try FURL.URI := edURI.Text;
TIdFTP(FIdFTP).ConnectTimeout := 60 * 1000; TIdFTP(FIdFTP).TransferType := ftBinary;
if FURL.Username <> '' then begin TIdFTP(FIdFTP).Username := FURL.Username; TIdFTP(FIdFTP).Password := FURL.Password; end;
TIdFTP(FIdFTP).Host := FURL.Host; TIdFTP(FIdFTP).IPVersion := FURL.IPVersion;
TIdFTP(FIdFTP).Passive := True;
TIdFTP(FIdFTP).Connect();
FPWorkerFile := PChar(FWorkerFileName); TIdFTP(FIdFTP).Get( FURL.Document, FPWorkerFile, False );
TIdFTP(FIdFTP).Disconnect;
finally FreeAndNil(FIdFTP); FreeAndNil(FURL); end;
except on e : Exception do ShowMessage( 'Exception - ' + e.Message ) end; |
Scheint mir ein Problem mit der Indy-Komponente zu sein welche IPv6 noch nicht so richtig handhabt. Denn versuche ich das ganze mit der IPv4 Adresse des Servers, funktioniert es.
Bin um jede Hilfe dankbar,
middel86
jaenicke - Mi 08.08.12 06:00
Eigentlich sollte die Komponente EPSV schon seit einigen Jahren können. :gruebel:
Da bleibt wohl nur im Quelltext zu schauen. Vielleicht muss man dafür etwas einstellen.
Benutzt du die aktuellste Version?
// EDIT:
Ein Blick (20 Sekunden) in die IdFtp.pas sagt mir, dass du (laut Kommentar) die NAT Extensions nach RFC 2428 aktivieren musst. Ein weiterer Blick sagt mir, dass es dafür reichen sollte UseExtensionDataPort auf True zu stellen. ;-)
middel86 - Mi 08.08.12 08:41
Hallo jaenicke!
Danke für deine Antwort. Leider bringt das auf True setzen des UseExtensionDataPort Flags nichts, da es während des Connects in der Komponente selbst wieder auf False gesetzt wird. Dies geschieht bei folgender Prüfung:
Delphi-Quelltext
1:
| FUsingExtDataPort := IsExtSupported('EPRT') and IsExtSupported('EPSV'); |
Beide IsExtSupported Aufrufe liefern False zurück, da der FTP-Server auf die FEAT Anfrage folgende Antwort gibt:
| Zitat: |
Command: FEAT
Response: 211-Features:
Response: MDTM
Response: REST STREAM
Response: SIZE
Response: MLST type*;size*;modify*;
Response: MLSD
Response: UTF8
Response: CLNT
Response: MFMT
Response: 211 End |
Diese Antwort wird ja dann in die StringList FCapabilities geschrieben und mit IsExtSupported() geprüft ob die beiden Ausdrücke 'EPRT' und 'EPSV' enthalten sind. Da dies nicht der Fall ist wird FUsingExtDataPort auf False gesetzt und während der PUT oder GET Operation SendPassive() anstelle von SendEPassive() aufgerufen...
Soweit wie ich das verstanden habe, sollte der FileZilla FTP-Server eigentlich die 'EPRT' und 'EPSV' Commands unter den Features auflisten, tut dies aber nicht. Die anderen FTP-Clients scheinen aber keine Probleme damit zu haben...keine Ahnung wieso.
Weitere Vorschläge sind sehr willkommen...
middel86
p.s.: Ja ich benutze die aktuellste Version der Indy-Komponente.
jaenicke - Mi 08.08.12 08:48
Stimmt, ich habe kurz nochmal reingeschaut. Soweit ich das sehe sollte es aber reichen AutoIssueFEAT auf False zu setzen, so dass IssueFEAT gar nicht erst aufgerufen wird. Dann werden die Features beim Login nicht geprüft.
middel86 - Mi 08.08.12 11:30
Super das hat den PASV Fehler behoben, danke!
Aber jetzt bekomme ich eine neue Exception beim GET:
| Zitat: |
| EIdSocketError: Socket Error # 11001 Host not found |
Das Problem ist, dass beim connect zum DataChannel als Host die IPv6 Adresse verwendet wird, aber als FIPVersion (TIdTCPClientCustom) der Default Wert Id_IPv4 genommen wird. Dann kann natürlich die IP-Adresse nicht aufgelöst werden.
Gibt es für hierfür auch ein magisches Flag welches ich noch nicht gesetzt habe? :?
Danke für deine Hilfe!
jaenicke - Mi 08.08.12 11:56
Ein Flag nicht, aber mir fällt da das Event OnDataChannelCreate ins Auge. Ich schätze mal darin kannst du das setzen. Den Channel bekommst du ja als Parameter. Und der Connect passiert erst danach. ;-)
(Also sprich (ADataChannel as TIdTCPClient).IPVersion := ...)
middel86 - Mi 08.08.12 12:32
Yeah, super jetzt hats endlich funktioniert!!
Ein fettes DANKE an dich jaenicke, jetzt kann die IPv6 Umstellung kommen! :D
Gruss
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!