# TCP Socket auf Verbindungsabbruch prüfen



## Fohnbit (9. Mrz 2017)

Hallo!

Ich baue und halte einen TCP Socket aufrecht.
Nun kann aber sein, das manchmal über Minuten/Stunden keine Daten gesendet werden müssen.

Aber mich muss dennoch einen Verbindungsabbruch erkennen.
Aber darf keine Daten über den Socket senden, sonst reagiert die Gegenseite.
Ich sende Daten über den Socket mit einer InnerClass:

```
/** Inner class representing the Consumer side */
    class Consumer extends Thread {

        public void run() {
            while (true) {
                byte[] b = null;
                synchronized (list) {
                    while (list.size() == 0) {
                        try {
                            // System.out.println("CONSUMER WAITING");
                            list.wait(); // must own the lock
                        } catch (InterruptedException ex) {
                            System.out.println("CONSUMER INTERRUPTED");
                        }
                    }
                    b = list.removeLast();
                    list.notifyAll();
                    // int len = list.size();
                    // System.out.println("List size now " + len);
                    // if (done)
                    // break;
                }

                long timeDifference = (lastTransmissionTime + getPropertyDelayout()) - System.currentTimeMillis();

                if (timeDifference > 0) {
                    try {
                        // System.out.println("Sleep " + timeDifference);
                        Thread.sleep(timeDifference);
                    } catch (InterruptedException e) {

                        e.printStackTrace();
                    }

                }

                process(b); // Outside synch section (could take time)
                // yield(); DITTO
            }
        }

        void process(byte[] b) {
            try {
                if (b == null || getOutputState() != 3) {
                    return;
                }
                lastTransmissionTime = System.currentTimeMillis();
                socket1.getOutputStream().write(b);

            } catch (Exception e) {
                updateOutputError("[ERROR] Sending Message: " + e.getMessage());
                if (shouldBeConnected) {
                    reConnect();
                } else {
                    disconnect(false, false);
                }

            }

        }
    }
```

Daten empfange ich vom Socket über einen Thread:

```
public void run() {
        InputStream is = null;
        try {
            is = socket.getInputStream();
            in = new BufferedInputStream(is);
        } catch (IOException e) {
            try {
                socket.close();
            } catch (IOException e2) {
                System.err.println("Socket not closed :" + e2);
            }
            parent.error("Could not open socket : " + e.getMessage(), false);
            parent.disconnect(false, false);
            return;
        }

        while (!desonnected) {
            try {
                byte[] got = readInputStream(in); // in.readLine();
                if (got == null) {
                    parent.error("Connection closed by client", false);
                    break;
                }
                parent.receiveNewBytes(got, false);
            } catch (IOException e) {
                if (!desonnected) {
                    parent.error(e.getMessage(), "Connection lost", false);
                }
                break;
            }
        } // end of while
        try {
            is.close();
            in.close();

        } catch (Exception err) {
        }
        socket = null;
    }// end of run
```


----------



## mrBrown (9. Mrz 2017)

Fohnbit hat gesagt.:


> Aber mich muss dennoch einen Verbindungsabbruch erkennen.
> Aber darf keine Daten über den Socket senden, sonst reagiert die Gegenseite.


mWn nicht möglich, du musst Daten senden, um zu erkennen ob sie gesendet werden können.


----------



## Times (27. Mrz 2017)

Wieso reicht dir das denn nicht aus wenn der Verbindungsabbruch erst beim Senden stattfindet?
Du kannst ja dann immernoch die Verbindung neu aufbauen und die Datei nach dem Neuaufbau versenden.


----------



## JuKu (11. Apr 2017)

Bei TCP hast du ja eine virtuelle Verbindung, da gibt es bestimmt Mittel & Wege.
Außerdem kannst du alle x Sekunden einen Heart Beat zum Server senden.


----------



## mrBrown (11. Apr 2017)

JuKu hat gesagt.:


> Bei TCP hast du ja eine virtuelle Verbindung, da gibt es bestimmt Mittel & Wege.


Nein, gibt es außer einem nicht gewünschtem Heartbeat nicht.


----------



## JuKu (12. Apr 2017)

Man könnte noch einen Timeout setzen, wenn innerhalb dieses Zeitraumes keine Daten empfangen wurden, wird ein Heart Beat gesendet.
Anders scheint es ja nicht zu gehen.


----------



## DrZoidberg (12. Apr 2017)

Aber dein Code erkennt doch schon ob die Verbindung geschlossen wurde und ruft daraufhin "parent.error" auf. Mehr brauchst du nicht.


----------



## mrBrown (12. Apr 2017)

DrZoidberg hat gesagt.:


> Aber dein Code erkennt doch schon ob die Verbindung geschlossen wurde und ruft daraufhin "parent.error" auf. Mehr brauchst du nicht.


geschlossen ist was anderes als ein Abbruch


----------



## DrZoidberg (12. Apr 2017)

Bei einem Abbruch wird eine Exception geworfen und "parent.error" ebenfalls aufgerufen.


----------



## mrBrown (12. Apr 2017)

DrZoidberg hat gesagt.:


> Bei einem Abbruch wird eine Exception geworfen und "parent.error" ebenfalls aufgerufen.


Nein, eben nicht.


----------



## DrZoidberg (12. Apr 2017)

Über was für eine Art von Abbruch reden wir hier? Timed die TCP Verbindung einfach aus oder wird da ein FIN oder RST Packet empfangen?


----------



## mrBrown (13. Apr 2017)

Ein "LAN-Kabel wurde durchgeschnitten"-Abbruch


----------



## DrZoidberg (14. Apr 2017)

In dem Fall kann man die keep-alive Funktion aktivieren mittels "Socket.setKeepAlive(true)".  Ausserdem sollte man noch die Zeit bis zum Senden von keep-alive Paketen verkürzen. Unter Windows mit HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\KeepAliveTime und in Linux mit /proc/sys/net/ipv4/tcp_keepalive_time.


----------



## mrBrown (14. Apr 2017)

Das keep-alive was optional ist und ein umkomfigurieren des Rechners erfordert (was andere Applications dann auch wieder überschreiben können...) und auch nicht von allen Netzwerkstacks unterstützt wird? Klingt immer super 

warum fügt man dem Protocol nicht einfach einen Heartbeat hinzu?


----------



## JuKu (18. Apr 2017)

Sehe ich so wie @mrBrown .


----------



## JStein52 (18. Apr 2017)

JuKu hat gesagt.:


> Sehe ich so wie @mrBrown .


Ich eigentlich auch. Aber der TE hat sich schon vor anderthalb Monaten abgekoppelt und seitdem gibt es keine neuen Erkenntnisse


----------

