Ich habe eine Reihe von TCP-Sockeln mit Keep-Alive (Intervall 1 min), gesteuert von einem select(2)
loop (Auswahl zum Lesen).
select(2)
einen Fehler zurück, wenn Keep-Alive-Timeout für einen der Sockets in der Menge aufgetreten ist? read(2)
zurückgeben?
select()
selbst gibt keinen Fehler zurück, wenn ein Fehler für einen der ausgewählten Sockets gemeldet wird. [Tatsächlich kann die API auf diese Weise keine Socket-Fehler anzeigen, da zwei verschiedene Sockets während eines einzelnen Aufrufs von select()
jeweils einen ausstehenden Fehler erhalten könnten. Welchen würde select()
zurückgeben?] select()
verwenden Sie stattdessen das Makro FD_ISSET, um eine read()
für jedes mit lesbar markierte Socket zu versuchen. select()
kehrt zurück, wodurch Sie zeitgesteuerte Fehler aufgrund von Keep-Alive sofort erkennen können. Beachten Sie, dass das Markieren eines Sockets zum Lesen nicht anzeigt, dass Daten zu lesen sind, sondern nur, dass ein Leseversuch nicht blockiert wird. Wenn der Socket einen ausstehenden Fehler hat, wird das Lesen nicht blockiert. Sowohl read(2)
als auch write(2)
rufen zuerst alle ausstehenden Fehler im Socket ab, bevor sie überhaupt versuchen, mit Daten umzugehen.
Ein Deskriptor gilt als lesbereit, wenn ein Aufruf an eine Eingabefunktion mit O_NONBLOCK clear nicht blockiert, ob die Funktion Daten erfolgreich übertragen würde oder nicht. (Die Funktion kann Daten zurückgeben, eine Dateiendeanzeige oder einen anderen Fehler, der anzeigt, dass sie blockiert ist, und in jedem dieser Fälle gilt der Deskriptor als bereit zum Lesen.) [ POSIX: select () ]
ETIMEDOUT
, wenn das andere Ende vollständig verschwindet. Wenn ein Paketübermittlungsfehler auftritt, werden Sie dies stattdessen durchmachen (wenn also das Keep-Alive-Paket eine ICMP-Fehlerantwort erhält, wie "Host nicht erreichbar", wird EHOSTUNREACH
geliefert). [Weitere Einzelheiten zu diesen Fällen finden Sie unter Stevens, "Unix Network Programming, Bd. 1".] select()
setzt ein Bit in FDSET
, das anzeigt, welches Socket ausgelöst wurde. Verwenden Sie FD_ISSET Makro, um festzustellen, welcher Socket nach dem Dienst gefragt wird.