# BufferedReader.ready() wird nicht true



## jiuka (14. Dez 2010)

Hallo,
kann mir jemand mit folgendem Problem helfen?: 

```
server = new Socket(servername, 587);
        
      
        DataInputStream in = new DataInputStream(server.getInputStream());
        DataOutputStream out = new DataOutputStream(server.getOutputStream());
        BufferedReader smtpIn = new BufferedReader( new InputStreamReader(server.getInputStream()));

        if (server != null) {
	        text= "EHLO " + InetAddress.getLocalHost().getHostAddress() + "\n";
	    	out.write(text.getBytes());
	        out.flush();
   
	        System.out.println("ready: " + smtpIn.ready());
	        while ( smtpIn.ready() ){
	        	System.out.println(smtpIn.readLine());
	        }
```
...warum wird der smtpIn.ready() nicht true? es sind eindeutig zeichen drin. die kann ich auch auslesen.
danke vorab
christian


----------



## HoaX (14. Dez 2010)

a) Woher weißt du dass was drin ist? Aus dem von dir gezeigen Codestück lässt sich das jedenfalls nicht ableiten.
b) DataInputStream und InputStreamReader parallel auf dem Socket sind böse!


----------



## jiuka (14. Dez 2010)

hallo,
um den datainputstream geht es garnicht. das war nur ein versuch um zu schauen wie groß die available bytes sind..  ich weiß das da was drin ist weil ich daraus auch etwas auslesen kann. soll ich dir den consolenoutput schicken? ;-)
lg christian


----------



## HoaX (14. Dez 2010)

Was du da treibst ist sinnfrei:

Wenn du zuerst einen DataInputStream erzeugt, kann es sein dass dieser schon ohne sonstiges zutun schon Daten liest, ich weiß grad nicht genau wie das interne Protokoll aussieht.
Der BufferedReader wird diese Daten niemals sehen, da sie schon gelesen sind. Der BufferedReader selbst puffert die Daten auch, wie der Name vermuten lässt. Was dieser also schon eingelesen hat - du aber noch nicht abgerufen hast - wird auch nie im DataInputStream auftauchen.
Soviel zu dem parallel Streamzugriff, sovas macht man nicht, man nutzt immer nur einen, dann kann man sicher sein dass auch nur an dieser Stelle die Daten ankommen und nicht die Hälfte hier und die andere Hälfte woanders.

Wenn du Daten an den Server schickst, dann müssen diese ja erstmal übertragen werden, und die Antwort des Servers auch, wenn er die Anfrage denn mal irgendwann verarbeitet. Wenn du also direkt nach deinem flush() mit ready() schaust ob was da ist, dann kommt da natürlich mit hoher Wahrscheinlichkeit false zurück, so schnell ist nirgendwo das Internet.
Lass doch einfach mal die while-Schleife mit dem ready() weg. Lies lieber die Javadoc zu BufferedReader#readLine(), dann wüsstest du, dass die Methode von sich aus schon wartet bis eine komplette Zeile angekommen ist. Das macht nämlich deine ready()-Schleife überflüssig.

Btw: Bei der gezeigen Konstellation kann server nicht null sein ...


----------



## jiuka (14. Dez 2010)

Hallo,
Danke! Du bist ein Schatz. Nach all deinen bösen Anschuldigungen war das was ich übersehen habe dabei. Ich mache das natürlich auch nicht parallel! Aber der Hinweis mit der Zeit war sehr hilfreich. Im übrigen ist die Schleife sehr sinnvoll wenn man mehr als eine Zeile an Antworten erwartet. Vielen Dank auch für den Hinweis mit Server. Ich habe da nur ins blaue geraten und ging davon aus, wenn die Adresse-Port Kombination nicht stimmt, stünde da noch null drin... vielen vielen Dank 
Christian


----------



## HoaX (14. Dez 2010)

Nein, auch bei mehreren Zeilen ist sie nicht sinnvoll. Wieso sollte es? Wenn du 5 Zeilen erwartest, wer sagt, dass die alle auf einmal kommen und nicht erst zwei und dann zehn Sekunden später nochmal drei? In diesen zehn Sekunden wird ready() auch false liefern -> bringt nix.

Btw: Smtp brauchst du nicht selbst implementieren, gibts mit JavaMail schon fertig.


----------



## jiuka (14. Dez 2010)

Du gehörst wohl auch zu den Leuten, die immer das letzte Wort haben müssen? ^^
Also der Server gibt am Stück aber in unbekannter Menge die Nachrichten zurück. Z.B. Antwortet der mit allem, was er beherrscht. So kann es sein, dass einer die Verschlüsselung beherrscht. Ein anderer aber nicht. D.h. die Anzahl der Nachrichten kann sich schon mal mindestens um eins unterscheiden. Deshalb die Schleife.
lg Christian


----------



## Michael... (14. Dez 2010)

```
String message;
while ((message = smtpIn.readLine()) != null){
                System.out.println(message);
}
```


----------



## jiuka (14. Dez 2010)

Darf ich dich zitieren? Das Internet ist nicht so schnell. Das würde das gleiche Problem mit sich bringen. Wenn man ohne Zeitpuffer den Buffer anspricht ist der natürlich auch wieder leer.
lg Christian


----------



## HoaX (15. Dez 2010)

Eben nicht. readLine() wartet bis die nächste vollständige Zeile empfangen wurde oder der Stream geschlossen wird. Also entweder man liest mit readLine() bis null zurück kommt, dann wurde der Stream geschlossen, oder man wertet die empfangenen Daten aus und weiß wann man nichtmehr lesen muss, bzw. man weiß vorher wieviele Zeilen kommen.

Selbst wenn der Server mehrere Zeilen "auf einmal" sendet, wie immer man das deuten mag, so heißt das nicht dass diese auch zusammen ankommen. Bedingt durch z.B. MTU kann ein gesendetes großes Paket auch als fünf kleine ankommen. Wie du mich richtig zitierst: Das Internet ist nicht so schnell, hat verschiedene Routen etc, deine Schleife mit ready() bricht mit hoher Wahrscheinlichkeit bereits zu einem Zeitpunkt ab, an dem du das nicht willst.

PS: Ich muss nicht das letzte Wort haben, mir liegt nur daran dich auf deine (gedanklichen) Fehler hinzuweisen. Ich bin mir durchaus bewusst, dass ich dem Fragenden selten Honig um den Mund schmiere, aber irgendwann gibt man halt auf und konzentriert sich aufs wesentliche, die Fehler. Ich mein es wirklich nicht böse wenn ich manche Dinge manchmal etwas barsch formuliere.


----------



## SebastianM (15. Dez 2010)

Nein, readLine() blockiert (wie alle read Operationen in der Standard-I/O), hat Hoax aber auch schon oben geschrieben.


----------

