Socket TCP keep alive Exception wird nicht ausgelöst

M

maddriver

Gast
Hallo ich habe folgendes Problem:

Für eine TCP verbindung setze ich socket.setKeepAlive(true). Das aktiviert auch die Keep Alives vom Protokollstack des Betriebssystems. Ich habe das mit dem Wireshark überprüft, soweit so gut.
Das einzige Problem an der Sache ist, das ich keine Exception bekomme wenn ich dann tatsächlich das Netzwerkkabel ziehe. Wenn ich irgendwelche anderen Daten (also außer dem Keep Alive des Betriebssystems) sende, bekomme ich eine Connection closed Exception, und genau das Verhalten würde ich auch von den Keep Alives erwarten, aber es passiert einfach nicht. Hat da jemand erfahrung oder weiß jemand was man da tun kann?
P.S.: Ich habe dasselbige mit Qt probiert und da funktioniert es einwandfrei, nur muß ich jetzt leider für ein Projekt auf Java umsteigen und das dort implementieren.

Ach ja im Betriebssystem hab ich das Keep alive Intervall auf eine Sekunde und die Keep alive time auf 3 Sekunden gesetzt, und dazu 10 Wiederholungen. Wie gesagt nach etwa 10 sekunden kommt in QT das Signal das die Connection zum Host abgebrochen ist, eben durch die Keep Alives, aber in Java passiert das nicht,obwohl ich Keep Alives aktiviert habe , die auch vom Client gesendet werden.

Hierzu mal ein bischen sourcecode:
Java:
static void openLANConnection(String IP,int Port){
		if (connectionactive==false)
		try {
			Networksocket = new Socket(IP,Port);
			Networksocket.setKeepAlive(true);
			out = new PrintWriter(Networksocket.getOutputStream(), true);
			in = new BufferedReader(
			new InputStreamReader(Networksocket.getInputStream()));
			connectionactive=true;
			
	} catch (SocketException e) {
		System.out.println("Socket Exception\n");
		e.printStackTrace();
		} catch (UnknownHostException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (IOException e) {
		System.out.println("Failed to Connect! Connection lost!\n");
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
 
M

maddriver

Gast
Ist während des wartens auch ein Thread da, der read auf in versucht, und blockiert ? Weil da würde wenn die exception kommen.

Ach brauche ich das in Java unbedingt? Hm naja dann muß ich halt nen Thread machen, das war mir jetzt so nicht bewusst! In Qt übernimmt das wohl die API irgendwie, denn da braucht man kein Thread, da gibbets einfach nen Signal das dann ausgelöst wird. Ich dachte das wär in Java ähnlich implementiert. Also sollte ich generell nen Thread machen der auf nen Input wartet und dann halt irgendwann die Exception generiert.

Aber da stellt sich mir noch eine Frage. Ich habe bis jetzt in der Application immer ein sehr einfaches Protokoll gefahren: Ich sende Daten und hole mir gleich danach die Antwort. (Es ist einfach nicht mehr nötig, da der Server keine Trap nachrichten verwendet, also keep Things simple :))
Wenn ich jetzt aber in einem eigenen Thread ständig den InputStream lese,"nur" wegen der keep Alive Exception, würde das ja dann unter Umständen nicht mehr funkrionieren da mir der Thread ja dann eventuell die Response nachrichten "klaut", oder kann ich den dann mit der Datenlänge 0 lesen, da keep Alives ja keine Daten beinhalten.
 

Empire Phoenix

Top Contributor
Im Thread selber kannst du doch die antworten lesen, und dann zb in eine BlockingQueue packen.
Dann kannst du an der anderen stelle einfach versuchen das oberste element aus der Queue holen.

-> Deine methode blockiert bis etwas in der Queue ist,
-> Der Thread liest antwort packt diese in Queue
-> Deine methode bekommt die Antwort und läuft weiter.
 
M

maddriver

Gast
Im Thread selber kannst du doch die antworten lesen, und dann zb in eine BlockingQueue packen.
Dann kannst du an der anderen stelle einfach versuchen das oberste element aus der Queue holen.

-> Deine methode blockiert bis etwas in der Queue ist,
-> Der Thread liest antwort packt diese in Queue
-> Deine methode bekommt die Antwort und läuft weiter.

Ja so mache ich das in komplizierteren Anwendungen ja in der Regel auch. Aber da hier quasi nur ein Serielles Protokoll implementiert wird, dachte ich, ich kanns mir sparen. Ich werde es jetzt mit einem loopback machen, das bietet das Protokoll an.

P.S: ich hab das mal mit dem Thread und dem Blockenden lesen implementiert. Und das lustige daran ist nun wieder, dass es egal ist ob ich ein Keep Alive im socket mache oder nicht. Er wirft eine Exception mit oder ohne diese Option. Das ist ja an und für sich nicht schlecht, aber es wirft bei mir irgendwie die Frage, warum man die KeepAlive option setzen kann, wenn man die Rückmeldung eh nich auswerten kann.
Ich will das nur mal kurz prezisieren: Wenn ich auf einen TCP socket, über das Betriebssystem ein KeepAlive verordne, dann laüft das normalerweise so. Das Betriebsystem handelt die KeepAlives seperat von dem was so normalerweise an Daten über den Socket geht, ein keep Alive enthält selbst keine Daten (ebensowenig ein KeepaliveAck) also werd ich mit Java auch nie etwas über den Stream sehen. Nun ist es aber so, dass wenn nach einer gewissen Zeit die KeepAlives verloren gehen, wegen einem Verbindungsabbruch, dann sagt das Betriebssystem dem socket connection reset.
Aber das abzufangen oder irgendwie mitzukriegen scheint in Java nicht vorgesehen zu sein?!?
Ich meine es würde mich nicht wundern , wenn man diese option überhaupt nicht setzen könnte, aber ,dass man sie setzen kann, aber dann nicht auswerten find ich irgendwie krass.
Vielleicht gibts ja auch doch irgendwie eine Möglichkeit wie man das tut (hätte mich halt nur persönlich interressiert) aber ich hab jetzt schon laaange im Internet gesucht und werde es nun wohl mit besagtem Loopback oder der Que probieren.

P.S.: Nichts gegen JAVA (falls das so rüberkommt), ich find JAVA persönlich toll, vor allem wie schnell man hier was zusammengebaut hat ohne sich ständig über das Einbinden von Bibliotheken oder irgendwelche kompiler gedanken machen zu müssen. Plattformunabhängig ist es auch noch. Spart einem viiiiieeeel Zeit.
 
T

tuxedo

Gast
AFAIK funktioniert TCP KeepAlive mit Java bestens. Problem ist, dass der Verbindungsabbruch nicht zeitnah erkannt wird, da die KeepAlive-Pakete nicht ständig durch die Leitung sausen. Man kann zwar das OS tweaken um die KeepAlive Frequenz zu erhöhen, aber das ist ja nicht im Sinne des Erfinders. Diese Einstellung gilt in der Regel OS-weit für alle Anwendungen. Das könnte andere Anwendungen negativ beeinflussen. Und da man ja auch noch mit Java entwickelt, kann man nicht (immer) mit Sicherheit vorhersagen auf welchem OS die Anwendung benutzt wird.

Von daher gibt's nur einen Ausweg (und der gilt nicht nur für Java, sondern für andere Sprachen auch):
Man braucht ein Protokoll-eigenes KeepAlive. Siehe dazu auch: socket : Java Glossary

Wenn man Kommunikationsframeworks wie MINA oder Netty benutzt, hat man den Komfort, dass dort IDLE-States ausgelöst werden, wenn die Verbindung eine gewisse Zeit brach liegt. Diese IDLE-Events lassen sich dann prima für ein eigenes KeepAlive nutzen. Einfach eine minimalste Nachricht zum gegenüber senden, welcher die Nachricht in einer bestimmten Form erwidern muss. Kommt in einer vordefinierten Zeit X kein Reply oder tritt sogar eine IOEXception (o.ä.) auf, kann die Verbindung als gestört angenommen werden. Ein weiterer netter Nebeneffekt: Man kann damit gleich die RTT messen ;-)

Gruß
Alex
 
M

maddriver

Gast
AFAIK funktioniert TCP KeepAlive mit Java bestens. Problem ist, dass der Verbindungsabbruch nicht zeitnah erkannt wird, da die KeepAlive-Pakete nicht ständig durch die Leitung sausen. Man kann zwar das OS tweaken um die KeepAlive Frequenz zu erhöhen, aber das ist ja nicht im Sinne des Erfinders. Diese Einstellung gilt in der Regel OS-weit für alle Anwendungen. Das könnte andere Anwendungen negativ beeinflussen. Und da man ja auch noch mit Java entwickelt, kann man nicht (immer) mit Sicherheit vorhersagen auf welchem OS die Anwendung benutzt wird.

Von daher gibt's nur einen Ausweg (und der gilt nicht nur für Java, sondern für andere Sprachen auch):
Man braucht ein Protokoll-eigenes KeepAlive. Siehe dazu auch: socket : Java Glossary

Wenn man Kommunikationsframeworks wie MINA oder Netty benutzt, hat man den Komfort, dass dort IDLE-States ausgelöst werden, wenn die Verbindung eine gewisse Zeit brach liegt. Diese IDLE-Events lassen sich dann prima für ein eigenes KeepAlive nutzen. Einfach eine minimalste Nachricht zum gegenüber senden, welcher die Nachricht in einer bestimmten Form erwidern muss. Kommt in einer vordefinierten Zeit X kein Reply oder tritt sogar eine IOEXception (o.ä.) auf, kann die Verbindung als gestört angenommen werden. Ein weiterer netter Nebeneffekt: Man kann damit gleich die RTT messen ;-)

Gruß
Alex

Hm also das ist das was ich hier immer im Internet lese. Speziell das mit dem Systemweiten Keep Alive Times und Keep Alives Interval, aber Fakt ist, dass das so einfach nicht stimmt, zumindest nicht ganz:)...
1. Ja es ist möglich KeepAlive Einstellungen Systemweit zu setzen, die dann für alle anwendungen gelten, die das KeepAlive vom OS setzen.
2. Es ist aber auch möglich diese Einstellungen nur für einen Socket zu setzen. Es wäre ja auch vollkommen sinnlos wenn man dies nur global für alle setzen könnte, da sonst ja keine Apllikation, sinnvoll verwenden könnte, wie du ja schon selbst erkannt hast. Das das in Java vllt. nich geht,o.k., aber mit c geht das sehr wohl. Hier mal aus der linux socket API (geht aber über die Windows API auch):

There are also three other socket options you can set for keepalive when you write your application. They all use the SOL_TCP level instead of SOL_SOCKET,[ and they override system-wide variables<b> only for the current socket<\b>]. If you read without writing first, the current system-wide parameters will be returned.


TCP_KEEPCNT: overrides tcp_keepalive_probes

TCP_KEEPIDLE: overrides tcp_keepalive_time

TCP_KEEPINTVL: overrides tcp_keepalive_intvl



Und nebenbei war meine Frage nicht wie man diese Einstellungen setzen kann, denn das hab ich schon getan, und es funktioniert einwandfrei. Meine Frage war wie ich in Java mitbekommen kann, dass es einen socket reset gab, der durch das (fehlen des) Keep alive ausgelöst wird.
Im übrigen bin ich mir sicher, dass dieser korrekt ausgelöst wird. Wie gesagt ich hab das mal mit Qt getestet, und mit java sehe ich die keep alives auch, wenn ich das mit dem wireshark angucke, nur eben bekomme ich das socket reset auf dem in java erstellten socket vom Betriebssystem nicht mit, obwohl es vom Betribssystem ausgelöst wird.
 
T

tuxedo

Gast
Okay, hab ich vergessen dazu zuschreiben: Das individuelle SocketKeepAlive gibt's in der Java-Welt, wie du bereits geschrieben hast nicht. Ergo bleibt einem, wenn man das ganze trotzdem beeibnflussen möchte, nur ein Application-Level-KeepAlive.

Damit du den TCP-KeepAlive mitbekommst, musst du irgendwas mit der Verbindung tun. Typischerweise ein "read()" auf den Stream des Sockets. Wenn du gar nix mit dem Socket machst, also weder read() noch write()... Wo soll der Fehler denn aufschlagen?! Es gibt hier keinen DefaultSocketExceptionHandler. Ergo: read() ... Mir fällt jetzt auch kein UseCase ein wo man kein read() machen wollte. Von daher: read() und gut ist.

Gruß
Alex
 
I

irgendjemand

Gast
use-case wo man *so gut wie* kein read() braucht :

stream-server

das einzige was hier gelesen werden muss ist die anforderung des clients welchen inhalt er haben möchte ...

*einfach nur um das beispiel zu geben bei dem man bis auf einen initial-schritt kein read() braucht =D*
 
T

tuxedo

Gast
Hmm, okay. Ist aber schon sehr speziell dass der Stream-Empfänger nach dem aktivieren des Streams dem Server nix mehr mitzuteilen hat.
Ein "read()" würde hier trotzdem niemandem weh tun. Und wenn man pro Client keinen separaten read() Thread spendieren will, kann man auch mit einem Timeout ein read() nach dem anderen absetzen und so mit einem (oder eben weniger als 1 pro Client) Thread alle bedienen.

Evtl. sollte man sich auch mal Java NIO anschauen. Da könnte das nochmal anders laufen (da non-blocking io), so dass man kein explizites "read()" Kommando braucht.

- Alex
 
M

maddriver

Gast
Danke für eure Hilfe, ich werd das dann mit dem read() ( hat halt nix mit keep alive zu tun , da keine Datenbits im Keep alive) machen[java erkennt das dann auch, ohne es angeschaltet zu haben]. ich habs auch eigentlich schon eingebaut, und es funktioniert:) Ich wollte nur so höflich sein und euch nochmal zu antworten, auf das keep alive thema.

P.S.: Jemand der die Berechtigung hat den Thread zu schließen kann das dann auch tun sofern er mag...:)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
L Keep Alive bei TCP/IP Netzwerkprogrammierung 5
N SOCKET mehrere Requests, keep Alive serverspezifisch? Netzwerkprogrammierung 3
T Webserviceaufruf verursacht eine Exception Netzwerkprogrammierung 3
R Socket FATAL EXCEPTION MAIN bei Socket based client/server app Netzwerkprogrammierung 2
D Exception Handling bei In/Outputsockets in eigenen Threads Netzwerkprogrammierung 1
A Cast Exception bei einfachem RMI Beispiel Netzwerkprogrammierung 3
M Socket Exception tritt auf - weiß nicht weiter Netzwerkprogrammierung 3
K Socket Exception Connection reset Netzwerkprogrammierung 9
C ObjectInputReader wirft beim zweiten Aufruf eine Exception Netzwerkprogrammierung 3
G Exception: Connection reset by peer: socket write error Netzwerkprogrammierung 2
A Socket Socket Verbindung unterbrochen --> keine Exception Netzwerkprogrammierung 7
H Socket Closed Exception verhindern Netzwerkprogrammierung 3
M RMI unmarshaling exception ??? Netzwerkprogrammierung 2
D Socket Streams schliessen .. Exception gewollt? Netzwerkprogrammierung 4
K Socket Socket Exception Netzwerkprogrammierung 3
eQuest RMI Unserializable Exception Netzwerkprogrammierung 4
F Bekomme NoSuchElement Exception Netzwerkprogrammierung 5
S RMI Exception Netzwerkprogrammierung 2
T rmi ssl zu große Objekte übergeben -> Exception Netzwerkprogrammierung 10
clupus Exception beim Schließen eines Sockets Netzwerkprogrammierung 6
G Exception javax.naming.CommunicationException Netzwerkprogrammierung 16
G Nullpointer Exception - Multithreading Netzwerkprogrammierung 25
G XML-RPC -> Exception $Proxy0-Unknown Source-No such handl Netzwerkprogrammierung 8
T Exception serialisieren? Netzwerkprogrammierung 5
K öffnen des socket schlägt fehl -> ABER: keine exception . Netzwerkprogrammierung 2
M ois nicht null, aber ois.getObject liefer exception Netzwerkprogrammierung 3
R ObjectOutput- / ObjectInputStream Exception? Netzwerkprogrammierung 2
D EA-Exception Network Adapter macht probleme Netzwerkprogrammierung 2
F Java Mail . Exception java.lang.NoClassDefFoundError Netzwerkprogrammierung 2
M Exception in thread "main" java.lang.NoClassDefFou Netzwerkprogrammierung 2
J JavaMail Exception bei senden an anderen Server. Netzwerkprogrammierung 8
M schreiben auf geschlossenen Socket ohne Exception Netzwerkprogrammierung 6
R LINUX: getHostAddress() und getHostName() werfen Exception Netzwerkprogrammierung 6
8 PrintWriter Exception Netzwerkprogrammierung 3
D socket exception + timing probleme Netzwerkprogrammierung 2
A Exception bei Cookie lesen Netzwerkprogrammierung 2

Ähnliche Java Themen

Neue Themen


Oben