C / TCP-Socket-Server / Client verliert Internetverbindung

Genius

Mitglied
Hallo Community,

ich programmiere immer noch an meinem Socket-Server und ein Problem bekomme ich einfach nicht vernünftig in den Griff.

Ich verarbeite je 64 Verbindungen in einem Thread mit select().

Mein Problem ist jetzt - das mein Server die socket-Verbindung zu clients offen hält, die während sie verbunden waren ihre Internetverbindung verlieren. recv() gibt dann nämlich leider nicht 0 zurück. Wie bring ich in Erfahrung, ob eine Socketverbindung tot ist weil der Client seine Internetverbindung verloren hat?

Gibt es wirklich nur die Möglichkeit eines Heartbeats der alle x-Sekunden einmal Daten hin und her schickt?

Ich freu mich auf eure Ideen und Antworten.

Mit freundlichen Grüßen
Genius
 
Du kannst, nachdem du mit select() das Handle geholt hast, auf dem der Disonnect eingetreten ist, mit ioctl() (bei Windows ioctlsocket()) prüfen, wieviel Bytes anliegen. Im Falle eines Disconnects sind as 0. Verwende für ioctl() den Befehl FIONREAD.
 
Du solltest eigentlich kein Problem damit haben, da irgendwann ein TCP Timeout greifen sollte, welcher dir dann via select() am entsprechenden Socket gemeldet wird. Sollten bei Linux um die 20 Sekunden sein. Bei Windows weiß ich es nicht. Ansonsten muss dein Server irgendeinen Fehler haben (im Programm oder gar OS selbst).

Ich selbst arbeite nicht mit select(), aber es könnte sein, dass du dafür das 3. FD-Set (exceptfds) nehmen musst. Ansonsten taucht es bei readfds mit 0 oder -1 bei recv() auf.
 
Zuletzt bearbeitet:
Hatte noch was reineditiert.

Unter Linux nutze ich epoll, under Windows IOCP. Für BSD gibt es noch kqueue (hab ich selbst aber noch nie genutzt).
 
select() löst doch nicht aus (und setzt fd_read) wenn ein Client die Internetverbindung verliert oder?

Da geb ich dir recht. Das Problem ist hier ziemlich gut beschrieben: http://nitoprograms.blogspot.de/2009/05/detection-of-half-open-dropped.html

Was kann man machen?

Du baust um dein Socket-Handle eine Struktur, die ein Element beinhaltet, wann das letzte mal Daten reingekommen sind. Mit select() bekommst du ja den Handle, und kannst mit irgendeiner beliebigen Funktion (z.B. clock_gettime() mit CLOCK_MONOTONIC) die Empfangszeit aktualisieren. Ist nach einer gewissen Zeit (liegt bei dir z.B. für 2 Min) für ein Handle kein Traffic aufgetreten, trennst du den Socket serverseitig. Dann wird der Client darüber informiert, oder auch nicht - je nach dem, ob eine physikalische Trennung stattgefunden hat oder nicht.
 
Gibt es bei epoll eine schönere Lösung als Heartbeats?

Denn das eintragen und überprüfen der Zeit ist zwar eine Möglichkeit - ist aber ja nichts anderes als ein Heartbeat.

Trotzdem Danke!
 
Ich muss gestehen, das ich bisher immer direkt mit einem Pseudo-Ping (wegen bestimmten Berechnungen) gearbeitet habe. Daher ist mir das wohl nie aufgefallen, dass bei einem gezogenen Kabel, etc. nichts ausgelöst wird. Wenn sich also so verhält, wie es saftmeister und du es sagen, dann bleibt dir nichts anderes übrig, als einen kleinen Zeitstempel pro socket zu verwaltet anhand dessen du einen potentiellen Verbindungsabbruch feststellen kannst.
 
Zurück