Senden und Empfangen mit TIdTelnet

Alle Fragen zur Netzwerkkommunikation
Antworten
Kay
Beiträge: 134
Registriert: So 14. Nov 2010, 15:17

Senden und Empfangen mit TIdTelnet

Beitrag von Kay »

Hallo,

ich möchte in meinem Programm eine Telnetveribndung aufbauen. Hierfür nutze ich die Komponente TIdTelnet und implementiere die Methode für OnDataAvailable:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
begin
  IdTelnet1.Host := 'localhost';
  IdTelnet1.Port := 23;
  IdTelnet1.Connect;
end;
 
procedure TForm1.IdTelnet1DataAvailable(Sender: TIdTelnet; const Buffer: String);
begin
  ShowMessage(Buffer);
end;


Zum Senden habe ich folgende Methode implementiert:

Code: Alles auswählen

procedure TForm1.SendTelnetCommand(S: String);
var
  I: Integer;
begin
  for I := 1 to Length(S) do IdTelnet1.SendCh(S[I]);
  IdTelnet1.SendCh(#13);
end;


Nun sende ich zwei Befehle, die beide eine Ausgabe liefern müssten:

Code: Alles auswählen

procedure TForm1.Button2Click(Sender: TObject);
begin
  SendTelnetCommand('eins');
  SendTelnetCommand('zwei');
end;


Mein erstes Problem besteht darin, dass das Ereignis OnDataAvailable nie ausgelöst wird. Offensichtlich werden die Kommandos nicht übermittelt, obwohl ich dachte, dass #13 doch eigentlich ein Kommando abschließt?

Und meine zweite Frage bezieht sich auf die Zuordnung der Antworten. Die Variable Buffer enthält ja einfach nur Text. Woher weiß ich jetzt aber, ob dieser Text zu Befehl "eins" oder zu Befhl "zwei" gehört? Möglicherweise werden gar keine zwei Ereignisse ausgelöst, sondern beide Ausgaben kommen gleich in einem Buffer. Theoretisch könnte ja sogar die Reihenfolge nicht mal stimmen...

Vielen Dank schonmal und viele Grüße
Zuletzt geändert von Lori am Sa 3. Aug 2013, 11:08, insgesamt 1-mal geändert.
Grund: Bitte den richtigen Highlighter nutzen


Kay
Beiträge: 134
Registriert: So 14. Nov 2010, 15:17

Re: Senden und Empfangen mit TIdTelnet

Beitrag von Kay »

Erstmal vielen Dank für den Tipp. Ich hab mir das Synapse-Paket heruntergeladen und in mein Projekt eingebunden.
Leider habe ich immernoch ein Problem bei der Erfassung einer Antwort auf einen gesendeten Befehl.

Code: Alles auswählen

TN := TTelnetSend.Create;
TN.TargetHost := 'localhost';
TN.TargetPort := '23';
TN.Timeout := 1000;
if TN.Login then
begin
  TN.WaitFor('Passwort:');
  TN.Send('abc');
  TN.WaitFor('>');
  ShowMessage('Bereit');
  TN.Send('xyz');
  ShowMessage(TN.RecvString);
end;


Die Bereitschaftsmeldung wird korrekt angezeigt, das Login sollte also funktioniert haben. Der RecvString ist allerdings dann komplett leer, d.h. ich bekomme keine Antwort auf das Kommando xyz, obwohl es eine Ausgabe erzeugt.

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Senden und Empfangen mit TIdTelnet

Beitrag von theo »

Wahrsch. musst du #13#10 als Abschluss senden wie in dem Bsp hier: http://sourceforge.net/mailarchive/mess ... id=6575033
Dort wurde zwar #$0d+#$0a genommen, ist aber dasselbe.

Code: Alles auswählen

telnet.Send('root'+#$0d+#$0a);

Thomas B.
Beiträge: 90
Registriert: Fr 2. Nov 2007, 13:32
OS, Lazarus, FPC: Win (L 1.0 FPC 2.6.0)
CPU-Target: 32Bit
Wohnort: Ulm

Re: Senden und Empfangen mit TIdTelnet

Beitrag von Thomas B. »

Wenn Du die Indy-Variante nochmal testen willst, dann probier mal mit

Code: Alles auswählen

IdTelnet1.IOHandler.ReadLn

direkt auf eine Antwort zu warten. Damit kann auch ein Timeout-Handling realisiert werden.

Antrepolit
Beiträge: 340
Registriert: Di 12. Sep 2006, 08:57
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Kontaktdaten:

Re: Senden und Empfangen mit TIdTelnet

Beitrag von Antrepolit »

http://www.delphipraxis.net/152874-indy ... endch.html
Da steht bereits, dass die Komponente wohl nicht sauber arbeitet. Was möchtest du denn eigentlich Programmieren?
Grüße, Antrepolit

care only if your os is really burning

Kay
Beiträge: 134
Registriert: So 14. Nov 2010, 15:17

Re: Senden und Empfangen mit TIdTelnet

Beitrag von Kay »

@Antrepolit: Ja, dass die Komponente etwas unsauber ist, glaube ich sofort.

@Thomas: Ich habe deinen Vorschlag mit der ReadLn-Methode getestet und es funktioniert einwandfrei. Allerdings müsste ich dann das Senden der Kommandos und das Zusammensetzen und Durchsuchen der Antworttexte selbst übernehmen. Daher werde ich höchstwahrscheinlich TTelnetSend nutzen, die Klasse scheint mir etwas flexibler zu sein und nimmt mir viel Arbeit ab.

@theo: Der Fehler lag tatsächlich am fehlenden #13#10. Jetzt funktioniert alles so, wie ich mir das vorstelle. Vielen Dank nochmal für den Tipp!

Eine Frage hätte ich allerdings noch: Lässt sich irgendwie feststellen, ob der Client noch mit dem Telnetserver verbunden ist? Ich hab die Spezifikationen durchgeblättert und jetzt auf Anhieb keine property Connected o.ä. gefunden. Oder muss ich eventuell try...except um jeden Send-Befehl bauen, um einen not-connected-error abzufangen? Wirft die Send-Methode überhaupt eine Exception?

Vielen Dank

Thomas B.
Beiträge: 90
Registriert: Fr 2. Nov 2007, 13:32
OS, Lazarus, FPC: Win (L 1.0 FPC 2.6.0)
CPU-Target: 32Bit
Wohnort: Ulm

Re: Senden und Empfangen mit TIdTelnet

Beitrag von Thomas B. »

Ich arbeite sowohl mit den Indy-Komponenten als auch mit Synapse. Beide laufen bei mir (in verschiedenen Projekten) sehr stabil.

Das Senden und das Parsen der Antworten muss man immer selbst übernehmen. In deinem Falle wird die Kommunikation sowieso synchron laufen, da ist das relativ einfach.
Wenn ich verschiedene Kommandos schicke, dann merke ich mir, von welchem Typ sie war, dann wird das Parsen der Antwort deutlich einfacher.
Bei der Kommunikation mit einer Hardware-Komponente gibt es üblicherweise einen festen Kommandoabschluss --> den einfach als DataTerminator beim ReadLn nehmen. Dann hast Du immer die komplette Antwort.

Bei Indy:
Vor dem Senden per Connected die Verbindung prüfen, und dann beim ReadLn Exceptions abfangen (z.B. wenn Verbindung abbricht, während man größere Datenmengen liest).
Bei größeren Datenmengen kann man mit IOHandler.InputBufferAsString sich den Teil-Inhalt schon mal zwischenzeitlich anschauen.
Nach einem Abbruch ggf. per IOHandler.InputBuffer.Clear wieder alles "aufräumen".

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Senden und Empfangen mit TIdTelnet

Beitrag von theo »

Kay hat geschrieben:Eine Frage hätte ich allerdings noch: Lässt sich irgendwie feststellen, ob der Client noch mit dem Telnetserver verbunden ist? Ich hab die Spezifikationen durchgeblättert und jetzt auf Anhieb keine property Connected o.ä. gefunden. Oder muss ich eventuell try...except um jeden Send-Befehl bauen, um einen not-connected-error abzufangen? Wirft die Send-Methode überhaupt eine Exception?


Das geht eher über LastError des TBlockSocket (Property Sock des TTelnetSend). Evtl. kann man auch auf das Antwort Timeout reagieren.
http://synapse.ararat.cz/doc/help/blcks ... #LastError

marcov
Beiträge: 1100
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Senden und Empfangen mit TIdTelnet

Beitrag von marcov »

Thomas B. hat geschrieben:Ich arbeite sowohl mit den Indy-Komponenten als auch mit Synapse. Beide laufen bei mir (in verschiedenen Projekten) sehr stabil.


Ich habe auch mehrere Jahre Indy genutzt, (samt 9 und 10), ohne bemerkenswerte Probleme. Für Telnet habe ich auch ICS genutzt, Synapse habe ich nie genutzt, war damals zu Linux spezifisch.

Was ich mich von Telnet erinnern kann, ist das es Telnet Emulation Properties gibt die zwischen Client und Server negotiated werden. (have _X usw). Dinge wie Line-endnung sind davon abhängig.

Antworten