Keep Alive bei TCP/IP

luk123

Mitglied
Hallo,

ich muss ein Keep Alive für eine TCP/IP Verbindung realisieren. Das heißt ich muss überprüfen ob die Gegenstelle noch nach Nachrichten horcht. Problem ist das die Verbindung noch aktiv sein kann. Weiteres Problem ist das ich nicht davon ausgehen kann das die Gegenstelle auf ein 'Testtelegramm' antwortet. Das heißt ich muss irgendwie überprüfen ob Nachrichten entgegengenommen wurden.

Java:
PrintWriter outPrintWriter = new PrintWriter(this.socket.getOutputStream(),
					false);

outPrintWriter.print(messageText);
outPrintWriter.flush();

outPrintWriter.checkError();

checkError liefert immer false zurück solange die Verbindung an sich noch aktiv ist. Hänge ich jetzt auf der Gegenstelle in einem Sleep fest wird aber trotzdem false zurück geliefert. Im falle eines Verbindungsabbruches, also der Socket wird geschlossen, wird true zurück geliefert....aber das bekommen ich ja auch so mit, durch eine Exception die geworfen wird.

Kann mir jemand bei meinem Problem helfen? Ich hoffe ich habs einigermaßen verständlich erklärt!

LG
 

xote

Mitglied
Soweit ich weiss, kann man das ACK Flag mittels
Code:
Socket.setKeepAlive(boolean on)
setzen. Wirft bei Fehlern eine Exception, aber genaueres sollte in der API zu finden sein.
 
T

tröööt

Gast
ähm ... KeepAlive ist eigentlich etwas der anwendungs-ebene ... nicht der transport-ebene ...

es ist aufgabe der software zu prüfen ob die gegenseite noch aktiv ist ... TCP stellt hier lediglich den kommunikations-kanal bereit ... und wenn die gegenseite so schlampig geschrieben ist das diese dem gegenüber nicht eindeutig mitteilt wann die verbindung getrennt werden kann ist das wohl kaum dein problem ... sondern ein protokoll-fehler ... bzw falls das protokoll sowas vorschreibt ein implementierungs-fehler ... das hat nichts mit TCP zu tun ... sondern mit deiner gegenstelle ...

wenn der entwickler dessen also mist gebaut hat gibts für dich keinen weg "sauber" an diese info zu kommen .. vor allem dann nicht wenn auf "ping"-pakete nicht reagiert wird ...
 

Bernd Hohmann

Top Contributor
Soweit ich weiss, kann man das ACK Flag mittels
Code:
Socket.setKeepAlive(boolean on)
setzen. Wirft bei Fehlern eine Exception, aber genaueres sollte in der API zu finden sein.

Die API gibt nicht viel her, denn das hängt alles von der Konfiguration des TCP/IP-Stacks des OS ab.

Grundsätzlich läuft das so: Wenn das Flag gesetzt wird und tcp_keepalive_time Sekunden keine Daten über den Socket geflossen sind werden danach zukünftig im Abstand von tcp_keepalive_intvl Sekunden automatisch Keepalive-Pakete gesendet. Schlägt das tcp_keepalive_probes mal fehl, wird die Connection als "tot" erklärt.

Blöderweise sind die genannten Parameter nicht von Java aus erreichbar und es ist auch nicht bekannt, auf welche Werte die eventuell von der Runtime gestellt werden.

Die Presets eines hundsgewöhnlichen Stacks sind eher konservativ und nicht zu gebrauchen:

tcp_keepalive_time = 7200 sek (2 Stunden)
tcp_keepalive_intv = 75 sek
tcp_keepalive_probes = 9

Bernd
 

Bernd Hohmann

Top Contributor
checkError liefert immer false zurück solange die Verbindung an sich noch aktiv ist. Hänge ich jetzt auf der Gegenstelle in einem Sleep fest wird aber trotzdem false zurück geliefert.

Das ist auch klar, denn der Socket lebt ja noch und wärend die Gegenseite schläft laufen die Daten halt dort in einen Puffer rein (zum Glück ist das so, denn andernfalls müssten meine Applikationen hier gehetzt die Daten Bitweise wegpollen damit es nicht zum Timeout kommt).

Um also auf der Anwendungsschicht festzustellen, ob die Anwendung noch lebt geht nur zuverlässig über ein Ping/Pong auf Anwendungsebene.

Ich hab Dir mal was gebastelt: Das lauffähige Snippent eröffnet einen ServerSocket, wartet auf eine Connection (die aus dem Thread kommt) und schiebt viele Daten rein. Obwohl es keinen Abnehmer auf der Serverseite gibt, flutschen die Daten durch und es gibt nirgendwo eine Exception.

Java:
import java.io.PrintWriter;
import java.net.*;

public class SocketTimeouts extends Thread {

	public static void main(String[] args) {
		try {
			new SocketTimeouts().start();
			ServerSocket ssok = new ServerSocket(4711, 1, InetAddress.getLocalHost());
			System.out.println("main() wait for incoming connection");
			Socket sok = ssok.accept();
			System.out.println("main() got connection, ideling");
			tunix(5000);
			System.out.println("main() closing connection");
			sok.close();
			ssok.close();
		} catch (Throwable t) {
			System.out.println("main() panic: " + t.toString());
		}

	}

	@Override
	public void run() {
		try {
			System.out.println("run() start");
			tunix(500);
			Socket sokRun = new Socket(InetAddress.getLocalHost(), 4711);
			PrintWriter pw = new PrintWriter(sokRun.getOutputStream());
			System.out.println("run() connected");
			for (int i = 0; i < 1000; i++) {
				System.out.println("run() sending part " + i);
				for (int k = 0; k < 1000; k++)
					pw.println("0123456789abcdefghijklmnopqrstuvwxyz");

			}
			sokRun.close();
			System.out.println("run() leave");

		} catch (Throwable t) {
			System.out.println("run() panic: " + t.toString());
		}

	}

	private static void tunix(long l) {
		try {
			Thread.sleep(l);
		} catch (InterruptedException e) {
			System.out.println("tunix(): " + e);
		}

	}

}
 

Ähnliche Java Themen

Neue Themen


Oben