# Java + Telnet ohne Library?



## DerKoenig (1. Februar 2011)

Moin Leude,

habe ne Frage zu Telnet mit Java.

Und zwar kann ich per Java nicht einfach einen Socket auf Port 23 mit dem Zielserver aufmachen und dann auf dem Output-Stream des Sockets die Telnet Befehle absetzen?

Bei mir klappt es nicht so richtig. Möchte möglichst um eine externe Library drum herum kommen.

Gruß und danke im voraus


----------



## Billie (1. Februar 2011)

Sollte eigentlich kein Problem sein - was genau funktioniert denn nicht? Fehlermeldung, etc. ?


----------



## DerKoenig (1. Februar 2011)

Ok ok, nein das Problem war keine Fehlermeldung, sondern kryptische Zeichen. Habe den BufferedReader benutzt. Das funktioniert so aber nicht, nutzt man den InputStream und wandelt die Rückgabewerte von Byte in String dann klappt alles wunderbar.

Gruß und trotzdem danke


----------



## Billie (1. Februar 2011)

Kommt darauf an welches Encoding dein Telnet-Server verwendet aber prinzipell solltest Du einem InputStreamReader immer ein Encoding mitgeben. Dann sollte es auch ohne das manuelle Umwandeln von byte in String funktionieren.


----------



## DerKoenig (1. Februar 2011)

Ah ok und wie tue ich jenes ? =) Mal so interessehalber


----------



## SE (1. Februar 2011)

das TELNET-protocol ist ein plain-test-protocol ...
encoding *so wie meine vorredner meinen* gibt es bei telnet nicht
wenn der server einen plain-string sendet dann kommt dieser auch genau so an ... und da telnet nur für die ersten 127 zeichen konzipiert ist *also bis 0x7F* muss für alles was darüber hinaus geht ein höheres protocol verwendet werden was für encoding gebaut ist ...
ansonsten verletzt dein telnet-server die RFC's ...
btw : vorher mal das protocol googlen und sich drüber informieren bevor man mit rumexperimentiert


----------



## Billie (2. Februar 2011)

Stimmt, mit dem TELNET-Protokoll an sich kenne ich mich nicht aus. Aber müsste folgendes nicht auch bei TELNET funktionieren?!

Klar, ist jetzt ein HTTP-Request, aber prinziepell die Ausgabe müsste doch ebenfalls Plain-Text sein?


```
try {
            final Socket client = new Socket("google.com", 80);
            Thread in = new Thread() {

                public void run() {
                    BufferedReader br = null;
                    try {
                        br = new BufferedReader(new InputStreamReader(client.getInputStream(), "US-ASCII"));
                        char[] cbuf = new char[128];
                        while (br.read(cbuf) > 0) {
                            System.out.println(cbuf);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        if (br != null) {
                            try {
                                br.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            };
            in.start();
            PrintWriter out = new PrintWriter(client.getOutputStream());
            out.println("GET / HTTP/1.1");
            out.println();
            out.println();
            out.flush();
            in.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
```


----------



## SE (2. Februar 2011)

du müsstest dann schonmal den GANZEN code posten ...
das diese try-konstrukt in einem THREAD oder RUNNABLE steckt erkennt man zum glück noch an dem 
	
	
	



```
).start();
```
aber ich glaube du gehst das etwas falsch an ..
du willst also ein http-request an einen server senden und dessen antwort ausgeben ...
und genau in dieser reihenfolge musst du es dann auch machen ... du kannst nich einfach ne verbindung aufbauen und dann lesen wenn der server nichts sendet sondern erstmal von dir ne anfrage erwartet ...
das sieht dann ungefähr so aus

```
Socket sock=new Socket("www.google.de", 80);
PrintStream out=new PrintStream(sock.getOutputStream());
BufferedReader in=new BufferedReader(new InputStreamReader(sock.getInputStream()));
out.println("GET http://www.google.de/ HTTP/1.0\r\n"); //OHNE die [URL]http://www.tutorials.de/java/ ... die setzt tutorial leider automatisch ein -.-* ... liegt halt am syntax-interpreter hier ...
String line=new String("");
while(true)
{
	line=in.readLine();
	if(line==null)
		break;
	System.out.println(line);
}
in.close();
out.close();
sock.close();
```

das beispiel is getestet und funktioniert
du musst dem server nur die richtige "frage" stellen und der server antwortet entsprechend

und warum verwendest du BufferedReader und bastelst dann mit char irgendwas da drum ?
HTTP ist auch PLAIN *wobei z.B. nicht lateinische zeichen in html-code geschrieben sein sollten ... ansonsten hast du wieder das encoding problem ... es sei denn der server verwendet UTF-8 ... das wird von BufferdReader zum glück automatisch dekodiert* und wird in der regel zeilen-weise gesendet ... darum kannst du bequem mit readLine() lesen ...
und wenn in html n zeilenumbruch erfolgen soll muss das mit <br> kodiert werden so das normale zeilenumbrüche zwar dazu führen das readLine() nur bis dahin liest und dann erneut aufgerufen werden muss ... aber im browser *oder HTML-fähigen Swing-Components* macht es keinen unterschied


----------



## Billie (3. Februar 2011)

Der Code ist so wie er ist in sich abgeschlossen, im einfachsten Fall kann man also einfach eine main-Methode darum packen und die Klasse ausführen. Und zumindest bei mir funktioniert der Code.

Natürlich kann ich von einer Verbindung lesen bevor ich Daten sende. Zum Beispiel beim SMTP-Protokoll sendet der Server als Reaktion auf die Verbindung eine Art "Begrüßung", ohne dass der Client reagiert hat. Das Lesen verlagere ich allerdings in eigenen Thread.

Beim HTTP-Protokoll wartet der Server halt zuerst auf eine Anfrage vom Client und das passiert im Beispiel ja auch sofort. Am Ende meines Programms warte ich dann noch mit join() auf das Ende meines lesenden Thread. Dieser endet, sobald der Server keine Daten mehr bereitstellt und die Verbindung schließt.

Die Variante mir char[] habe ich verwendet, weil ich nicht weiß ob beim TELNET-Protokoll ein CRLF zum Tragen kommt. Diese Variante sollte also auch eine Ausgabe liefern, wenn der Server kein CRLF sendet.

Den BufferedReader hätte ich mir da wirklich sparen können und außerdem habe ich die Buffer-Länge vergessen, folgende Variante ist evtl. sauberer:


```
public void run() {
                    InputStreamReader isr = null;
                    try {
                        isr = new InputStreamReader(client.getInputStream(), "US-ASCII");
                        char[] cbuf = new char[128];
                        int length = 0;
                        while ((length = isr.read(cbuf)) > 0) {
                            System.out.println(new String(cbuf, 0, length));
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        if (isr != null) {
                            try {
                                isr.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
```

Und um jetzt nocheinmal zum Ursprünglichen Problem Stellung zu nehmen. Ich glaube inzwischen im TELNET-Protokoll werden Steuerzeichen verwendet. Diese Zeichen können in der Konsole dann irgendwie ausschauen. Aber das ist nur eine Vermutung.

Beste Grüße,
Billie


----------



## SE (4. Februar 2011)

ja ... stimmt schon das steuerzeichen verwendet werden ... und zwar die ersten 32 bytes der ANSI / ASCII tabelle ... also (byte)0x00 bis (byte)0x1F
(byte)0x20 ist das 33te zeichen und entspricht nach beiden tabellen dem leerzeichen ... also das erste darstellbare zeichen
was dein CRLF angeht ... auch einzeln werden diese als zeilenterminierung verwendet ...
unix z.b. hat nur das LF als terminator ... während windows standardmäßig CRLF verwendet ... und wenn mans mal zum testen einbaut wird selbst ein aleinstehendes CR als terminator angesehen
die aussage das du erstmal was zum server senden musst bevor du eine antwort bekommst war jetzt nur auf HTTP beschränkt ... natürlich gibt es viele protocole bei denen der server bei verbindungsaufbau mit einer "begrüßung" reagiert ... darunter fällt auch FTP ...
und man sollte sowohl lesen als auch schreiben in eigene threads packen und nicht nur eines der beiden ... zumindest habe ich bei meinen codes dadurch performance-steigerung erreicht ... allerdings nur wenn im main-thread noch mehr passiert als nur die beiden anderen threads zu starten


----------



## Chefkoch333 (8. Februar 2011)

SPiKEe hat gesagt.:


> das TELNET-protocol ist ein plain-test-protocol ...
> encoding *so wie meine vorredner meinen* gibt es bei telnet nicht


 
<klugscheiss> ASCII ist auch ein Encoding. Übertragen werden schließlich 0 & 1. Wie daraus ein Buchstabe zu interpretieren ist beschreibt das Encoding.
Bei Telnet dürfte das Encoding aber in der Regel keine Rolle spielen da hier wie schon gesagt nur die ersten 127 Zeichen genutzt werden und die meisten Encodings auf ASCII aufbauen. 
Alternativ gibt es aber auch z.B. den ebcdic Zeichensatz der sich vom ASCII grundlegend unterscheidet.</klugscheiss>


----------



## SE (8. Februar 2011)

boar du banane ... man muss es ja auch bis runter auf OSI-1 auseinandernehmen ...
natürlich ist ASCII in dem sinne sicher ein encoding ... aber hier ging es um das encoding ab 0x80 ... und nicht um das bis 0x7F ...

no further comment


----------



## Chefkoch333 (9. Februar 2011)

Soweit muss man gar nicht runtergehen. In der Java Welt reicht es schon nur bis zum Input-/Output- Stream zu gehen welche mit Bytes arbeiten. Erst ein Reader oder Writer bringt ein Encoding (=Bytes als Zeichen interpretiert) ins Spiel. Mir ging es nur darum eine nicht korrekte Aussage zu korrigieren. 
Aber ich will hier keinen Streit vom Zaun brechen. Deshalb war mein Post ja auch mit klugscheiss-tags maskiert ;-)


----------

