Java Überprüfen ob Socket geschlossen wurde

Xot

-
ID: 413078
L
26 November 2006
451
36
Hallo zusammen,

ich habe folgendes Problem:
Ich habe einen InputStream von einem Socket und warte per
Code:
while (clientIn.available() == 0) {
					Thread.sleep(10);
				}
darauf, dass dieser "gefüllt" wird.

Das klappt auch soweit. Nur wenn ich den Client per TaskManager abschiesse und der Server an dieser Stelle ist, befindet er sich in einer Endlosschleife.

Nun möchte ich gerne vom Server her prüfen, ob der Socket auf dem Client noch offen ist.

s_client.isClosed() hilft leider nichts, da die Verbindung schon angenommen wurde.

Bleibt als einzige Lösung einen Timeout zu setzen oder gibt es eine elegantere Möglichkeit dafür?

Gruss,
Xot
 
korrekt, nebenbei liefert die available()-Methode des InputStreams immer 0 (Quelle), gebufferte Streams sollen diese Methode überschreiben.
 
korrekt, nebenbei liefert die available()-Methode des InputStreams immer 0 (Quelle), gebufferte Streams sollen diese Methode überschreiben.

Hmm also das kann ich so nicht bestätigen. Bei mir funktioniert das definitiv und ich habe zurzeit etwa so einen Code:
Code:
ServerSocket ss = new ServerSocket(localport);
Socket client = null;
client = ss.accept();
final InputStream streamFromClient = client.getInputStream();

while (client.available() == 0) {
	Thread.sleep(10);
}

Das funktioniert Problemlos. Sobald beim Server etwas ankommt, wird die Schleife verlassen.


Edit: Ich hab das ganze jetzt per Timeout gelöst. Trotzdem danke.
 
Laut Manual gibt des Sockets gibt die Available-Methode des InputStreams des Sockets die Anzahl der gebufferten Bytes zurück, also ist dies ein Spezialfall, bei dem es mal funktioniert, i.R. ist es nämlich anders.
 
Laut Manual gibt des Sockets gibt die Available-Methode des InputStreams des Sockets die Anzahl der gebufferten Bytes zurück, [...]
Aber nur die gepufferten? Es können also noch mehr Daten unterwegs sind, die noch irgendwo am Router oder im Betriebssystem hängen?
 
Aber nur die gepufferten? Es können also noch mehr Daten unterwegs sind, die noch irgendwo am Router oder im Betriebssystem hängen?
Wie so immer, JRE-specific ;)
Da steht keine genaue Definition, also ja.
Ich nehme jedoch mal an, dass dies direkt ein Aufruf an die Socket-Funktionen und deren available-Methode des BS ist.
 
Aber nur die gepufferten? Es können also noch mehr Daten unterwegs sind, die noch irgendwo am Router oder im Betriebssystem hängen?
Irrelevant, die JRE sieht die Daten erst wenn sie vom Netzwerkkartentreiber an das Programm weitergegeben wurden, das Programm kann doch nicht vorhersehen wie viele bytes da noch im Anflug sind.
available sagt lediglich wieviele Byte noch im System Buffer sind, also im Buffer in dem die Packete geordnet und nach oben hin freigegeben werden (ich gehe mal von TCP aus).
Es mag zwar so aussehen als sei der InputStream nicht gebuffert aber TCP wird immer gebuffert um defragmentation und in-order delivery zu gewaehrleisten.
Man kann aber einen gebufferten stream drumwrappen, auch wenn das nur Sinn macht wenn man Zeilenweise auslesen will oder bytes zurueckpushen will.

Sleep is auch nich so toll BTW. Wenn du noch andere Threads am laufen hast empfiehlt sich Thread.yield() damit giebst du die Kontrolle an einen anderen Thread ab, aber hast die chance bei einem interrupt sofort selber wieder dranzukommen (neue Daten da). Aber achtung wenn du nur Threads hast die yielden hast du Thrashing und sleep waere besser.

Hoffe es hilft :D
 
In der Theorie korrekt, in der Praxis nicht zu 100%.
Ich habe mal in einem Whitepaper der Sun JRE gelesen, dass sowohl sleep als auch yield ungefähr gleich implementiert sind. Mit yield gibst du eben die Kontrolle ab und kannst beim nächsten Thread-Switch wieder drankommen, bei sleep ist eben garantiert, dass du erst wieder drankommst wenn mindestens die angegebene Zeit abgelaufen ist.
Es wäre ja auch ne ziemlich doofe Implementierung, wenn bei einem sleep(1000) wirklich der Thread 1sek die Threadzuteilung hat aber nichts tut, das wäre ja extrem ineffizient.

Das ist auch wieder so ein Punk, denn Java macht in seinem JavaDoc dafür keine Garantie, es kann ja sein, dass man solch ein Vorgehen auf manchen OS nicht implementieren kann, deshalb lässt man es eben undefiniert, wie sleep seine Wartezeit verbringt, kann aber auf einigen Systemen effizientes Warten implementieren
 
Naja es macht insofern einen unterschied als dass direkt nach dem Aufruf der Zustand eines Threads nach yield im ready Zustand und nach sleep im sleep Zustand ist. Das Problem is wenn alle Threads sich dauernd nur selber yielden dann wird sehr schnell kontext geswitcht und das fuehrt dazu dass der Zustand eines Threads geladen und sofort wieder entladen wird, was zu Thrashing fuehrt, waehrend bei sleep haettest du die garantie dass der Zustand nicht haeufiger geladen wird.
Hab's eigentlich auch nur nebenbei erwaehnt weil ich selber mal einen worker pool mit 48 Threads hatte und die haben's geschafft mit yield eine 8 Core maschine unbrauchbar zu verlangsamen, und mit sleep ging's besser :D