Entwickler-Ecke
Internet / Netzwerk - Telnet Client ist einfach zu schnell
Jocke - Do 16.08.07 09:41
Titel: Telnet Client ist einfach zu schnell
Hallo,
ich schreibe gerade an einem Programm, mit dem man mit einem PC ein Linux-Gerät per Telnet automatisch konfigurieren können soll, unter Verwendung der Telnet Komponente aus den Indys.
Auf dem Linux-Gerät sollen in der Telnet-Sitzung verschiedene Befehle ausgeführt werden, z.B. Wechseln in ein bestimmtes Verzeichnis, erstellen einer Script.sh mit dem Vi Editor, einfügen eines Textes in die Datei, Vi beenden, Datei verschieben , usw.
Bei der manuellen Eingabe über Telnet kein Problem.
Jetzt sollen die Telnet-Kommandos über das Programm gesendet werden, etwa so :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| Form1.IdTelnet1.Create(nil); Form1.IdTelnet1.Host:=Form1.Edit1.text; Form1.IdTelnet1.Connect; If Form1.IdTelnet1.Connected Then begin Form1.IdTelnet1.WriteLn('cd /home'); Form1.IdTelnet1.WriteLn('vi script.sh'); Form1.IdTelnet1.WriteLn('i'); Form1.IdTelnet1.WriteLn('cd /test'); Form1.IdTelnet1.WriteLn('tar xjf /prog/prog.tar.bz2'); Form1.IdTelnet1.WriteLn('cd /etc'); Form1.IdTelnet1.WriteLn('^['); Form1.IdTelnet1.WriteLn(':wq'); ... ... end; ... ... |
Mein Problem ist jetzt, dass die Kommandos vom Programm derart schnell gesendet werden, dass das Linux-Gerät mit dem Verarbeiten nicht hinterher kommt, d.h. ein Teil der Befehle ist schon gesendet, noch bevor sich die Telnet-Konsole meldet.
Ich bräuchte also irgend eine Verzögerung zwischen den einzelnen Befehlen, oder es gibt eine andere Möglichkeiten mit dem Absetzen eines Befehls solange zu warten, bis sich das Linux-Gerät entsprechend gemeldet hat.
Mit der Demo zum Indy TelnetClient komme ich nicht weiter, weil dort nur von einer interaktiven Telnet-Sitzung ausgegangen wird, d.h. die Befehle werden manuell abgesetzt.
Ich wäre froh, wenn mir hier jemand eine Denkanstoß geben könnte.
Vielen Dank
Narses - Do 16.08.07 10:36
Moin!
Eine Möglichkeit wäre auf eine Antwort bzw. Ergebnisnachricht zu warten - du kannst ja auch aus der Telnetsitzung lesen - und dann erst den nächsten Befehl abzusetzen. Bei Kommandos, die keine Ausgabe erzeugen, setzt du ein echo -continue- oder so dahinter, dann hast du auch wieder eine. :idea:
cu
Narses
Jocke - Do 16.08.07 10:59
Hallo Narses,
vielen Dank für Deine Antwort. (Übrigens hat mir auch dein Posting zu
Netzwerkkomponente verfügbar [
http://www.delphi-forum.de/topic_pruefen+ob+Netzwerkkomponente+verfuegbar+ist_74712.html] sehr weitergeholfen).
Narses hat folgendes geschrieben: |
Eine Möglichkeit wäre auf eine Antwort bzw. Ergebnisnachricht zu warten - du kannst ja auch aus der Telnetsitzung lesen - und dann erst den nächsten Befehl abzusetzen. |
Da habe ich auch schon dran gedacht, da ich die Antworten vom Linux-Gerät auf die Telnet-Befehle ja eigentlich kenne. Aber gerade hier stehe ich auf dem Schlauch. Komme ich hier mit idTelnet.ReadLn() weiter ? Oder wie kann ich die Antworten abfragen bzw. darauf warten.
Narses - Do 16.08.07 11:05
Moin!
Bitte, gern geschehen. :)
Jocke hat folgendes geschrieben: |
Aber gerade hier stehe ich auf dem Schlauch. Komme ich hier mit idTelnet.ReadLn() weiter ? Oder wie kann ich die Antworten abfragen bzw. darauf warten. |
Der Telnet-Client hat doch das Ereignis
OnDataAvailable()(zumindest in Indy9), damit hab ich das bisher immer gemacht. ;)
cu
Narses
Jocke - Do 16.08.07 12:23
Das bringt mich auf eine Idee.
Ich verwende bereits das Ereignis OnDataAvailable(), um die Telnet-Sitzung in einem Memofeld anzuzeigen.
Wenn ich nun am Ende der OnDataAvailable-Prozedur ein Boolean-Variable bereit:=true setze und dann in meiner Telnet-Prozedur so etwas mache wie
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| Form1.IdTelnet1.WriteLn('Befehl'); repeat until bereit=true; bereit:=false; Form1.IdTelnet1.WriteLn('nächster Befehl'); repeat until bereit=true; bereit:=false; Form1.IdTelnet1.WriteLn('nächster Befehl'); ... |
könnte das funktionieren ?
Narses - Do 16.08.07 12:44
Moin!
Ich würde das so nicht machen, das ist thread-style-programming in einer ereignisorientierten Anwendung... :? brrr! :| (so, wie´s da steht, geht´s nebenbei eh nicht, da das Ereignis nie eintreten würde). Zum Thema ereignisorientierte Programmierung:
FAQ-Beitrag [
http://www.delphi-library.de/topic_Ohne+CPULast+auf+Ereignisse+in+Formularanwendungen+warten_67969.html]. :les: ;)
Du könntest sowas machen:
- pack alle Befehle in eine TStringList("CmdList"), alle OK-Antworten in eine weitere ("RcList"), die Indices synchron halten
- Zeiger (=Integer) in die Listen ("P") auf 0 setzen, Verbindung zur LinuxBox aufbauen
- einen Messagehandler für eine eigene Nachricht ("CM_NextCommand") definieren
- wenn die Verbindung steht, wirst du wohl irgend eine Antwort erhalten -> das 1. Mal OnDataAvailabletritt ein
- im OnDataAvailableprüfst du, ob die Daten von der LinuxBox in RcList[P]stehen (=Antwort OK); wenn die Antwort NICHT OK ist, Abbruch :nixweiss: ist die Antwort OK, dann sich selbst CM_NextCommandposten und im Handler CmdList[P]senden, dann Pweiterzählen :arrow: im nächsten OnDataAvailablegeht´s dann wieder genau so
- der eigene Messagehandler ist deshalb nötig, um aus dem OnDataAvailable-Handler rauszukommen, sonst gibt das möglicherweise problematische Effekte (besonders, wenn dir irgend jemand den "Tipp mit APM" geben sollte... :?)
- auf diese Weise baust du eine Ereigniskette auf, die von dem OnDataAvailable-Ereignis gesteuert wird :idea:
- pack noch einen DeadMan-Timer mit rein (wird beim Senden gestartet und im OnDataAvailable immer wieder zurückgesetzt), der nach 5 Minuten oder so Abbricht, weil nix mehr zurück kommt
cu
Narses
Jocke - Do 16.08.07 13:33
Hallo Narses,
erst mal vielen Dank für deine wirklich ausführliche Hilfe.
Das muss ich mir alles mal genauer anschauen.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 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!