Hi zusammen, ich stehe gerade etwas auf dem Schlauch: Momentan arbeite ich an einem TCP-Server. Wenn der Client die Verbindung beendet und der Server danach ein Send() macht, dann stürzt der Server mit der Exception "external: SIGPIPE" ab. Das ist doof. aktuell sieht die Sende-Routine bei mir etwa so aus: a) select() auf TX-Event b) send(); Wie kann ich denn auf Server-Seite prüfen, ob der Client noch da ist? Die Idee mit dem select() auf TX hatte ich mal irgendwo gelesen, aber das funktioniert hier irgendwie nicht :( Mit einem Fehler im Return-Code könnte ich super leben, aber Absturz ist halt auf Dauer unbrauchbar... Falls es etwas hilft: Lazarus unter Linux Mint 18.3 select() und send() sind aus dem fpc-Wrapper fpselect() und fpsend(). Die sollten aber 1:1 auf die Linux-Funktionen gehen. Codeschnipsel müßte ich erst generieren (ist über ein paar Klassen in meinen eigenen Bibliotheken verteilt). Mit UDP hatte ich mit den selbst (Basis-)Klassen bislang nie Probleme, aber das liegt wahrscheinlich an der Verbindungslosigkeit Freue mich über jeden konzeptionellen Tip! :) Mir geht es hier wirklich um das Verständnis ums Konzept "Erkennen einer geschlossenen TCP-Verbindung", nicht um das Zusammenkopieren von Codeschnipseln! Danke und VG
Hi A.K. vielen Dank! Das ging ja schnell :) Gerade wollte ich schreiben: Ich hätte früher fragen sollen, dann wäre ich auch früher in den manpages über MSG_NOSIGNAL gefallen... Viele Grüße!
Hi, hier noch eine „konzeptionelle Anmerkung“: Das Flag-Bit MSG_NOSIGNAL löst das Problem des Absturzes bei nicht abgefangenem SIGPIPE. Dieses Flag kann man sowieso immer setzen (und natürlich auch immer die Returncodes auswerten!). Das SIGPIPE entsteht, weil der Server noch versucht Daten zu senden, obwohl auch der lokale Socket schon weg ist. Der lokale Socket wird vom Client dadurch geschlossen, das der Reset (RST) schickt. Ein Reset kommt entweder weil auf dem Client ein „abortive Shutdown“ programmiert ist (SO_LINGER mit Intervall 0 (setsockopt()) und anschließend ein close()) oder weil nach dem close() des Clients nach Ablauf des Linger-Intervalls noch Daten beim Client ankommen. Das kann man auch im Server Programm berücksichtigen und das Problem möglicherweise allein damit lösen. Dazu muss man mit dem select() auch den readfds abfragen. Wenn der Client die Verbindung schließt, ob graceful oder nicht, dann setzt select() das Bit für read und man empfängt mit recv() 0 Byte und bekommt einen Returncode. Dann kann der Server ebenfalls die Verbindung schließen ohne unnötig weiter Daten zu senden. Wenn der Server allerdings Daten wie ein Fileserver sendet und deshalb beim Close oder Abbruch durch den Client schon genügend unterwegs sind, dann kann es wieder zu „broken pipe“ kommen. Deshalb, siehe oben, immer das Flag-Bit setzen :-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.