Java [InputStream] read(...) hängt fest; keine (zumindest äußere) Endlosschleife

T

Tersus

Gast
Grüßt euch,

wenn ihr mir helfen wollt, bitte den Beitrag nach dem Code gründlich lesen.^^ Lang ist er nicht. Vielen Dank schon mal dafür.

Ich übe mich derzeit an einem ganz simplen TCP-Server- und Client. Der Client sendet lediglich die Bytes {1, 2, 3, 4} an den offline Server, der diese Bytes zurück schicken soll. Mehr nicht.

Nun habe ich die Methode zum Lesen aus dem Socket-Inputstream ganz typisch und standardmäßig geschrieben. Findet man in jedem Tutorial.

TCP-Server:
Code:
byte[] leseNachricht(java.net.Socket socket) throws IOException{
	
	InputStream is = socket.getInputStream();
	ByteArrayOutputStream buffer = new ByteArrayOutputStream();
	
	byte[] block = new byte[256];
	
	int n;
	
	while( (n = is.read(block)) != -1 ){ // Hier hängt die Schleife beim zweiten Durchlauf
	
		buffer.write(block, 0, n);
	
	}
	
	buffer.flush();
	
	return buffer.toByteArray();
	
}

Beim 1. Schleifendurchlauf ist, wie zu erwarten, n = 4, die Variable block = {1, 2, 3, 4}. Alles in Ordnung.

Schon beim 2. Schleifendurchlauf, n ist ja noch nicht nicht -1, hängt is.read(block). Es wird keine Exception geworfen und die while-Schleife läuft auch nicht weiter -> keine Endlosschleife.

Wie ist das zu erklären? Worauf wartet die Methode, um zu terminieren?
 
public int read(byte[] b) throws IOException


This method blocks until input data is available, end of file is detected, or an exception is thrown.


der Stream wartet wohl auf Daten, die er lesen kann.
 
Mal als Denkanstoß: Warum denkst du denn, dass ein read von einem noch geöffneten Socket einfach so terminieren sollte? Das wäre ja ärgerlich. Du hast dem Server 4 Bytes geschickt, und die kamen auch an. Wer sagt denn aber, dass da nicht noch etwas in der Leitung hängt, das eben etwas später ankommt? Wenn du den InputStream mit einem File benutzt, dann funktioniert deine Logik. Denn der Stream weiß, wenn das File komplett gelesen wurde (EOF). Bei einem noch offenen Socket ist die Sache etwas anders.
 
Das ergibt natürlich absolut einen Sinn.

Ich dachte mir schon, dass das mit dem offenen Socket zusammen hängt ... .

Und schon hier wird ersichtlich, wieso ein simpler TCP-Server selbst für simpelste Szenarien definitiv nicht ausreichend ist. :-/
 
Ich wollte lediglich eine Folge von Bytes an den Server senden, der darauf hin mit einer Folge von Bytes antwortet. Da ich noch nie einen TCP Server/Client geschrieben habe, wusste ich nicht, dass es da diese "Schwierigkeiten" gibt.

Ich dachte ernsthaft, nach dem Senden meiner Bytes, antwortet der Server umgehend und alles ist Friede Freude Eierkuchen. ;-)

Da muss ich wohl mittels Threads ein Zeitfenster zum Auslesen geben.
 
Na das blockierende read ist da aber nicht das Problem. Die Schleife wird für dein {1,2,3,4} ja einmal ausgeführt und der buffer somit gefüllt, das Versenden müsste dann halt auch an dieser Stelle stattfinden. Dann könnte dein Client soviel Senden wie er möchte (auch nach langer Pause) und wird alles zurückbekommen. Sobald der Client dann das Socket schließt, blockiert auch das read nichtmehr.
 
Zuletzt bearbeitet:
crvn075 schrieb:
Na das blockierende read ist da aber nicht das Problem. Die Schleife wird für dein {1,2,3,4} ja einmal ausgeführt und der buffer somit gefüllt, das Versenden müsste dann halt auch an dieser Stelle stattfinden.
Doch, das blockierende read ist ein Problem. Die Folge {1, 2, 3, 4} war nur beispielhaft. Ich kann die Schleife also nicht gleich nach dem ersten Mal abbrechen. Was, wenn ich den Block tatsächlich überschreite? Dann würde was fehlen. :-/
 
Du schickst die Daten einfach im Schleifenrumpf zurück. Deine Blockgröße ist momentan 256 byte groß. Wenn also in einem Schwung Daten reinkommen, die kleiner gleich 256 bytes groß sind, wird die komplette Nachricht bei der ersten Iteration zurückgesendet und danach wartet read weiter. Sind die Daten jedoch größer, beispielsweise 942 bytes, dann läuft die Schleife eben vier mal durch bis alles wieder zurückgesendet wurde (256 + 256 + 256 + 174 = 942), erst danach blockiert read wieder.

Tersus schrieb:
Dann würde was fehlen. :-/

Die Schleife ist ja gerade deswegen da, damit nichts fehlt :)
 
Zuletzt bearbeitet:
Zurück
Oben