Socket Verbindungsverlust unter Linux erkennen

Bernau

Mitglied
Hi Leute,

ich habe leider keinerlei passenden Thread gefunden und richte mich deshalb direkt an euch :)

Erst mal ein paar Hintergrundinfos:
In einem Client-Server-Projekt das als RCP-Applikation mit Eclipse unter Windows programmiert wird, habe ich ein Kommunikationsprotokoll gebaut, dass Objekte serialisiert vom Client zum Server (und andersherum) verschickt.

Der Verbindungsverlust:
Da der Verbindungsverlust nur beim Schreib- oder Leseversuch erkannt werden kann, wird regelmäßig ein Statussignal verschickt. Unter Windows kommt es beim Versenden des Signals zur SocketException falls die Verbindung abgebrochen ist (z.B. WLAN-Empfang weg, zum Test Netzwerkkarte deaktiviert, ...) und wird entsprechend behandelt (Dialog vs. Auto-Reconnect je nach Programmstatus).

Jetzt zur eigentlichen Frage:
Unter Linux sendet der Socket am Client auch nach deaktivieren der LAN-Verbindung fröhlich weiter Nachrichten, die ins Nirvana laufen. Nach ca. 3-5 Minuten kommt dann erst eine TimeoutException die auch entsprechend abgefangen wird.
Ist die Implementierung der Sockets in der JVM unter Linux anders aufgebaut? Wie kann ich den Verbindungsverlust früher erkennen? (unter Windows erfolgt die Erkennung beim nächsten Zugriff)

Java:
try{
	// while connected && ( connection not canceled OR something to send in queue)
	while(!destination.isClosed() && (!canceled || writeQueue.size()>0)){
		//wait for content
		try {
			//check for new messages
			if(is.available()>0){
				readObject();
			}
			//write messages to server
			writeMessages();
		} catch (ConnectException e) {
			Logger.getLogger(getClass()).warn("Verbindung verloren", e);
			connectionClosedReason = LOST_CONNECTION;
			break; // connection lost
		} catch (SocketException e) {
			Logger.getLogger(getClass()).warn("Verbindung verloren", e);
			connectionClosedReason = LOST_CONNECTION;
			break; //connection closed
		} catch (IOException e) {
			Logger.getLogger(getClass()).error("Fehler in der Kommunikation", e);
			connectionClosedReason = COMMUNICATION_ERROR;
			break;
		}
		
		//check connectivity
		long now = new GregorianCalendar().getTimeInMillis();
		long diff = now-lastAction;
		if( diff >= timeout){
			//send heartbeat if connection has been idle for a long time
			sendStatus(STATUS_ACTIVE);
		}
		//wait 
		sleep(50);
	}
}catch (Exception e) {
	Logger.getLogger(getClass()).error("Unerwarteter Fehler", e);
	connectionClosedReason = UNEXPECTED_ERROR;
}

Die Methode readObject() liest, falls vorhanden, das empfangene Objekt vom InputStream. writeMessages() sendet alle in der Queue befindlichen Nachrichten. Falls lange keine Nachricht verschickt wurde, wird ein "Heartbeat" gesendet um die Verbindung auf Gültigkeit zu prüfen.

Vielen Dank im Voraus :) Ich hoffe ihr könnt mir eine gute Idee geben, woran es unter Linux liegt.
Grüße,
Bernau
 

Empire Phoenix

Top Contributor
Ping-pong nachrichten wie deine status, client sagt ping, server antwortet mit pong, wenn mehr als x sekunden verzögerung sind (und y nachrichten nicht gepongt werden) als verbindungsabruch interpretieren.
 
T

tuxedo

Gast
Hmm, hab in SIMON ähnliches implementiert: Da wird ebenfalls, wenn die Verbindung herumidelt, PingPong gespielt um die Verbindung zu testen. Damit klappt die erkennung eines Verbindungsaufalls zuverlässig, und in abhängigkeit des Idle-Timeouts (der zeit bis die Verbindung als idle anzusehen ist) ziemlich schnell.

Welche JVM benutuzt du unter Linux? habs zuletzt mit einer Oracle 1.6 JVM 64bit getestet. Mit Java 7 und OpenJDK hab ichs allerdings noch nicht explizit getestet.

- Alex
 

Bernau

Mitglied
Ich verwende aktuell Ubuntu 10.04 LTS x86 und java-6-openjdk.

Vielen Dank für den Tipp mit der Antwort und dem Timeout. Ich hab gar nicht daran gedacht, weil ich auf die Fehlererkennung beim Socketabbruch fixiert war. Das PingPong-Prinzip werde ich implementieren und damit den Fehlercheck machen!

In welchen Zeitabständen sollte ich eurer Meinung nach die Verbindung testen?
Es sind aktuell 60 Clients die eine aktive Verbindung zum Server haben. Die allgemeine Netzwerkauslastung soll ja nicht unnötig durch übertriebenes gepinge steigen, die Zuverlässigkeit der Verbindung aber möglichst hoch sein (ich weiß, dass die beiden Punkte sich leider gegenseitig ausschließen).
Mein aktueller Ansatz zur Lastverteilung: Beim Verbindungsaufbau legen Client und Server zufällig ihr Timeout zwischen 20-40 Sekunden fest. Durch die zufällige Vergabe sollen identische Timeouts vermieden werden, da sonst beide Seiten gleichzeitig Pingen würden (und zukünftig jeder Pongen müsste). Zusätzlich soll so die Auslastung beim Server gleichmäßig verteilt werden (also jede Sekunde 1-5, statt jede Minute einmalig 60 Stück zusammen).
Es ist davon auszugehen, dass die Anzahl der Clients steigen wird, weshalb dieser Punkt relativ kritisch ist. Eine Idee in der Richtung wäre also auch sehr hilfreich :)

Grüße und nochmal vielen Dank,
Bernau
 
T

tuxedo

Gast
Ich weiß ja nicht was du für ein Protokoll fährst oder wie bei dir kommuniziert wird. Aber generell kannst dir ja auch sowas wie ein "idle-state-detector" bauen: Der erkennt wenn für den zeitraum X keine Kommunikation stattfindet. Erst dann triggerst du mit einem nicht-Retriggerbaren-Timer den Ping-Pong im Zeitabstand von Y. Sobald der normale Protokolltraffik wieder einsetzt, legst du den Timer still. Durch das stilllegen und wieder anstarten hast du dann auch das "Problem" mit dem vielen gleichzeitigen PingPongs vermieden...

Damit fahre ich bei SIMON recht gut. Wenn sowieso gerade kommuniziert wird, muss ich kein Ping-Pong machen. Dann übernimmt der normale Protokoll-Verkehr den Verbindungscheck (schlägt das Senden einer Nachricht fehl, ist wohl etwas faul). Ansonsten gerät die Verbindung irgendwann (Zeit X) in den Idle-State und dann wird PingPong gespielt. Ping-Pong-Pakete sind bei mir so klein wie möglich gehalten und werden auch so einfach wie möglich beantwortet.

X und Y kann man frei einstellen. Je schneller der Verbindungsabbruch erkennbar sein soll, desto kleiner muss X und Y gewählt werden (bis minimal 1sek). Damit steigt dann aber auch der Traffik. Wirklich kritisch ist das aber nicht: Weder der Traffik noch der Serveraufwand die Pings mit einem Pong zu beantworten haben sich als kritsich erwiesen. Selbst bei vielen Clients (deutlich >100).

Sowohl X als auch Y stehen bei SIMON defaultmäßig auf 30sek. 20 Sekunden wären so das typische Netzwerk-Timeout... Warum ich ausgereichnet 30sek gewählt hab: Gute Frage... Weiß ich nicht mehr.

- Alex
 

Bernau

Mitglied
Hallo tuxedo,

ich habe mich in meinem letzten Post leider etwas unglücklich ausgedrückt. Der "Timeout" von 20-40 Sekunden der da genannt wird ist die Zeit, nach der ein Ping gesendet wird, insofern in der Zeitspanne kein regulärer Traffic entstanden ist.
Bisher fehlte nur der "Pong" um zu verifizieren, dass die Verbindung wirklich aktiv ist. Ich habe mittlerweile den Pong mit 3 Sekunden Timeout eingebaut und werde das erst mal im kleinen Kreis testen. Wenn es funktioniert wird der neue Stand per Shell-Skript an die Clients deployed ;-)

Danke nochmal. Grüße,
Bernau
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
M JAX-WS unter Java 17 plötzlich nicht mehr möglich Netzwerkprogrammierung 5
G Programm unter anderer IP ausführen Netzwerkprogrammierung 6
Thallius HTTP HTTPS unter Java 1.6 schlägt fehl Netzwerkprogrammierung 4
B HTTP Webseite unter IP-Addresse nicht aufrufbar - unter Domain schon Netzwerkprogrammierung 9
windl URLConnection unter 1.7 macht Probleme Netzwerkprogrammierung 14
S soap kann nicht zu 127.0.0.1:8090 unter Windows verbinden Netzwerkprogrammierung 2
Dit_ FTP chmod | LIST unter Win und Unix Netzwerkprogrammierung 2
aze JPCap unter Windows 7(64 Bit) Netzwerkprogrammierung 6
S Problem mit 2 Serversockets unter Win XP Netzwerkprogrammierung 7
C RMI Klasse wird unter falschem Pfad gesucht Netzwerkprogrammierung 4
A Ping unter Java Netzwerkprogrammierung 5
K Wireless Programmierung unter Java? Netzwerkprogrammierung 3
G Fehlermeldung beim Erzeugen der WSDL Datei unter Axis Netzwerkprogrammierung 2
B Internetverbindung prüfen unter Windows Netzwerkprogrammierung 1
H freigabe - unterschiedliche pfade unter linux und windows Netzwerkprogrammierung 7
B Datei speichern unter Netzwerkprogrammierung 10
psysp Paket unter Linux broadcaste Netzwerkprogrammierung 2
A protokoll unter soap Netzwerkprogrammierung 3
R PID's auf remote PC unter Windows herrausfinden Netzwerkprogrammierung 2
A Socket unter Linux Netzwerkprogrammierung 4
FrankenDerStein HTTP Https Server Bibliothek für Linux und Android gesucht. Netzwerkprogrammierung 7
OnDemand Linux RAM per Thread Netzwerkprogrammierung 3
S Probleme bei Java-Installation auf Server (Linux/Shell/Terminal) Netzwerkprogrammierung 6
windl Windows vs Linux Netzwerkprogrammierung 11
U Socket Instant Messanger (Server Linux, Client Windows) Netzwerkprogrammierung 1
D Einfache Verbindung zu Linux Server und Datei auslesen Netzwerkprogrammierung 13
Dit_ UDP Port bestimmen | Windows, MAC, Linux... Netzwerkprogrammierung 2
multiholle RMI Verbindung Linux <-> Windows Netzwerkprogrammierung 4
T RMI delay windows(client) <-> linux(server) Netzwerkprogrammierung 11
W Tcpdump aktive Netzwerkverbindungen/Programme (Linux) Netzwerkprogrammierung 2
DeviAn Über ein Linux Server ein Windows Server nach einer File fragen Netzwerkprogrammierung 6
N Über Socket an Linux-Server Kommandos absetzen? Netzwerkprogrammierung 4
K Server Client läuft in Windows allerdings nicht in Linux Netzwerkprogrammierung 9
R LINUX: getHostAddress() und getHostName() werfen Exception Netzwerkprogrammierung 6
M IP Adressen auslesen und in Windows/Linux übergeben Netzwerkprogrammierung 5

Ähnliche Java Themen

Neue Themen


Oben