# Vom Socket lesen wenn das Gegenüber schon disconnected ist?



## Kalter Kaffee (22. Jan 2009)

Hallo zusammen

Seit gestern beschäftige ich mich mit Netzwerksockets. Kann es sein, dass auf die API-Dokumentation nicht viel Verlass ist?

Dort steht zu BufferedReader.readLine(): "returns a String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached. Throws: IOException - If an I/O error occurs". Oder zu InputStreamReader.read(): "returns the character read, or -1 if the end of the stream has been reached".

Was meinen die mit "end of stream"? Dass nichts mehr kommt, also Ende Fahnenstange ist doch erst gewiss wenn der Stream geschlossen wurde. Blos dann bekomme ich ja sowieso eine IOException oder wenn das Gegenüber die Netzwerkverbindung geschlossen hat auch eine SocketException. Widerspricht sich das nicht?

Mir sind da einige SMTP- und FTP-Server bekannt die bei Verbindungsherstellung nur kurz eine Busy-Meldung auswerfen und die Verbindung sofort wieder kappen. Die kann ich aber gar nicht erst lesen weil jeder read sofort von einer Exception beantwortet wird. Muß ich da andere Methoden verwenden um noch an die Meldung zu kommen?

Robert


----------



## SlaterB (22. Jan 2009)

wenn diese Reader auf eine Datei angewendet werden, kann man auf jeden Fall bis null/-1 lesen, 
dort gibts keinen vorzeitigen Abbruch, insofern macht die JavaDoc-Beschreibung schon Sinn,

bei Sockets vermute ich auch manchmal, dass dort die Verbindungen vielleicht beendet werden, bevor alle Daten gelesen wurden,
ob dem so ist kann ich mangels Erfahrung nicht sagen,
falls es für mich irgendwan mal wichtig wäre, würde ich es testen und dann wissen 

deine Argumentation, dass es dann bei Servern, die ihr Verhalten nicht großzügig anpassen, zu Problemen kommen kann, kann ich nachvollziehen,
aber auch nicht beantworten 

ich wollt nur das zu den FileReadern erwähnen


----------



## Gast2 (22. Jan 2009)

Moin,



			
				Kalter Kaffee hat gesagt.:
			
		

> Mir sind da einige SMTP- und FTP-Server bekannt die bei Verbindungsherstellung nur kurz eine Busy-Meldung auswerfen und die Verbindung sofort wieder kappen. Die kann ich aber gar nicht erst lesen weil jeder read sofort von einer Exception beantwortet wird. Muß ich da andere Methoden verwenden um noch an die Meldung zu kommen?



Du machst was falsch ... Du bekommst die BUSY-Meldung und der Socket wird vom Server geschlossen ... in dem Moment erhälst Du auch eine -1 beim Lesen (oder null)

entweder Du liest die BUSY-Meldung falsch vom Netzwerk (also bereits zuviele Bytes) oder Du liest nach dem Schließen des Sockets noch was vom Netzwerk ... beides endet in einer Exception

hand, mogel


----------



## Kalter Kaffee (28. Jan 2009)

mogel hat gesagt.:
			
		

> Kalter Kaffee hat gesagt.:
> 
> 
> 
> ...


Danke für eure Rückmeldungen. Ich glaube schon dass ich was falsch mache. Ich müsste nur rauskriegen wo.

Hat jetzt etwas gebraucht, aber inzwischen habe ich es etwas mehr getestet.
Bei einem kleinen Programm das in einem Thread einen ServerSocket aufmacht, ein paar Zeilen sendet und dann den Socket schließt funkioniert es wie es sollte. Der Client im Mainthread liest (nach einem sleep damit die Verbindung auch sicher schon zu ist) die Zeilen ein und erhält dann null vom nächsten readLine().

Sind es zwei getrennte Programme und ich starte den Serverteil, unterbreche dieses laufende Programm nach einer Zeile mittels Ctrl+C  auf der Console, erhält der Client eine SocketException: Connection reset.

Wie denn das? Wo ist der Unterschied?

Robert


----------



## Ebenius (28. Jan 2009)

Im ersten Beispiel wird die Socketverbindung geschlossen. Im zweiten Beispiel wird sie unterbrochen. Es ist doch ein Unterschied, ob sich Dein Kollege verabschiedet und nach hause geht, oder kommentarlos aus dem Fenster springt.


----------



## SlaterB (28. Jan 2009)

kommentarlos könnte man ja auch eher als 'läuft ewig weiter' interpretieren,
sendet das Betriebssystem irgendein Abbruchsignal oder werden bestimmte Kontrollnachrichten nicht mehr gesendet/ beantwortet?


----------



## Ebenius (28. Jan 2009)

SlaterB hat gesagt.:
			
		

> kommentarlos könnte man ja auch eher als 'läuft ewig weiter' interpretieren,
> sendet das Betriebssystem irgendein Abbruchsignal oder werden bestimmte Kontrollnachrichten nicht mehr gesendet/ beantwortet?


Dein Betriebsystem bekommt von dem Sterben des Programms auf der gegenüberliegenden Seite nichts mit. Es schmeißt einen Fehler, beim nächsten Versuch.


----------



## Kalter Kaffee (30. Jan 2009)

Ebenius hat gesagt.:
			
		

> SlaterB hat gesagt.:
> 
> 
> 
> ...


Naja, wenn das System auf der anderen Seite einfach abschmiert kann ich das verstehen.

Aber sollte das System beim Beenden eines lokalen Programms mit Ctrl+C nicht doch was mitkriegen? Darum ging es mir zwar nicht (sondern ums Schließen der TCP-Verbindung per FIN worauf mein Programm auch angemessen reagiert), aber verstehen möchte ich es doch gerne. 

Mit Wireshark habe ich die Unterschiede auf TCP-Ebene noch nicht feststellen können da das unter Windows leider den Loopback nicht beschnüffeln kann.

Robert


----------



## tuxedo (30. Jan 2009)

Wenn die Anwendung abschmiert, kriegt das OS das mit und schließt auch die Socketverbindung, bzw. signalisiert ein FIN oder sowas.

Anderes Szenario:

PC 1 <-----> Switch A <----> Switch B <---> Switch C <---> PC 2

Fällt Switch B aus, kriegt das weder PC1 noch PC2 mit. Da muss man dann schon "KeepAlive" einschalten, oder noch besser regelmäßig ein "Ping-Pong" zwischen PC1 und PC2 betreiben. Und wenn auf eine "Ping" Nachricht in einem vorgegebenen Zeitfenster kein "Pong" eintrifft, wird die Verbindung wohl gestört sein.

Hab ich bei meiner SIMON Implementierung auch gebraucht. Drauf gekommen bi nich dadurch:

http://mindprod.com/jgloss/socket.html#DISCONNECT

Gruß
Alex


----------



## Gast2 (30. Jan 2009)

Moin,



			
				tuxedo hat gesagt.:
			
		

> PC 1 <-----> Switch A <----> Switch B <---> Switch C <---> PC 2


da reicht schon die kurze Variante mit einem Switch ... selbst da kann man die Kabel ziehen und wieder stecken ... anschließend funktioniert die Verbindung immer noch - außer es wurde wärend der gezogenen Kabel versucht was zu senden ... dachte eigentlich bisher immer das das .NET-Framework Probleme macht ... liegt aber wohl am TCP Protokoll 



> Da muss man dann schon "KeepAlive" einschalten,


meinst Du *setKeepAlive(true)* ... ist das was internes von Java oder eine TCP-Implementierung?



> oder noch besser regelmäßig ein "Ping-Pong" zwischen PC1 und PC2 betreiben.


idealerweise sendet der Client dieses Paket regelmäßig und der Server reagiert nur darauf mit einer Antwort ... reduziert die Server-Last

hand, mogel


----------



## tuxedo (31. Jan 2009)

Jepp das ist das mit setKeepAlive(true). Und ja, das ist eine In TCP eingebaute Funktion. Du musst da selbst nix dran drehen oder an deinem Protokoll ändern. 

Da du aber keinen Einfluss darauf hast wann und wie oft TCP diese keepalive Pakete sendet kannst du das auch in dein Protokoll einbauen. Ich verwende das MINA Framework. Da hast du einen eingebauten Idle-Timer. Wenn die Verbindung eine gewisse Zeit brach liegt senden beide Seiten ein Pingpaket und starten einen Countdown. Kommt in dieser Zeit kein Pongpaket ist die Verbindung weg, oder die Gegenseite hängt fest. 

Finde die Lösung besser als die Sache mit dem TCP KeepAlive da man da sicher gehen kann dass die Gegenseite noch arbeitet. 

Gruß Alex


----------



## Gast2 (31. Jan 2009)

Moin,



			
				tuxedo hat gesagt.:
			
		

> Jepp das ist das mit setKeepAlive(true). Und ja, das ist eine In TCP eingebaute Funktion. Du musst da selbst nix dran drehen oder an deinem Protokoll ändern.



ich habe es jetzt auch im .NET Framework gefunden ... ist ganz schön versteckt gewesen ... werde aber beim wohl Ping-Pong bleiben

hand, mogel


----------



## Kalter Kaffee (12. Feb 2009)

Jetzt bin ich gerade wieder über eine neue Variante des Problems gestolpert.

Ich habe ja das oben erwähnte kleine Testprogramm. Das wenn das einfach vom Socket liest der schon zu ist, kommt der vorher erhaltene Text noch an. Wurde jedoch nach schließen durch die andere Seite aber vor dem Lesen noch etwas gesendet (was selbst keinen Fehler aufwirft), wird ein read() mit

```
Exception in thread "main" java.net.SocketException: Software caused connection abort: recv failed
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:129)
	at java.net.SocketInputStream.read(SocketInputStream.java:182)
        ...
```
beantwortet.

Toll, ich kann doch nicht vor jedem write testen ob in der Zwischenzeit eine Nachricht reinkam. Denn wenn nicht, blockt der read ist.

Wie soll man denn mit so einem inkonsistenten Verhalten umgehen?

Robert


----------

