Non è possibile rilevare il cavo Ethernet scollegato solo con la funzione call write(). Ciò avviene a causa della ritrasmissione tcp eseguita dallo stack TCP senza la tua coscienza. Ecco le soluzioni.
Anche se è già stata impostata l'opzione keepalive sul socket dell'applicazione, non è possibile rilevare in tempo lo stato di connessione guasto del socket, nel caso in cui l'app continui a scrivere sul socket. Ciò è dovuto alla ritrasmissione tcp da parte dello stack tcp del kernel. tcp_retries1 e tcp_retries2 sono parametri del kernel per la configurazione del timeout di ritrasmissione tcp. È difficile prevedere l'ora esatta del timeout di ritrasmissione perché è calcolata dal meccanismo RTT. Puoi vedere questo calcolo in rfc793. (3.7. Data Communication)
https://www.rfc-editor.org/rfc/rfc793.txt
Ogni piattaforme hanno configurazioni del kernel per tcp ritrasmissione.
Linux : tcp_retries1, tcp_retries2 : (exist in /proc/sys/net/ipv4)
http://linux.die.net/man/7/tcp
HPUX : tcp_ip_notify_interval, tcp_ip_abort_interval
http://www.hpuxtips.es/?q=node/53
AIX : rto_low, rto_high, rto_length, rto_limit
http://www-903.ibm.com/kr/event/download/200804_324_swma/socket.pdf
È necessario impostare valore più basso per tcp_retries2 (default 15) se si desidera rilevare presto morti connessione, ma è tempo non preciso come ho già fatto disse. Inoltre, attualmente non è possibile impostare tali valori solo per singolo socket. Quelli sono parametri globali del kernel. C'era qualche prova per applicare l'opzione socket di ritrasmissione tcp per singolo socket (http://patchwork.ozlabs.org/patch/55236/), ma non penso che sia stata applicata alla linea principale del kernel. Non riesco a trovare la definizione di queste opzioni nei file di intestazione di sistema.
Per riferimento, è possibile monitorare l'opzione presa keepalive tramite 'netstat --timers' come di seguito. https://stackoverflow.com/questions/34914278
netstat -c --timer | grep "192.0.0.1:43245 192.0.68.1:49742"
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (1.92/0/0)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (0.71/0/0)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (9.46/0/1)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (8.30/0/1)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (7.14/0/1)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (5.98/0/1)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (4.82/0/1)
Inoltre, quando capita per timeout keepalive, si possono incontrare diversi eventi di ritorno seconda piattaforme in uso, in modo che non si deve decidere lo stato della connessione morto solo da eventi di ritorno. Ad esempio, HP restituisce l'evento POLLERR e AIX restituisce solo l'evento POLLIN quando si verifica il timeout keepalive. Si verificherà l'errore ETIMEDOUT nella chiamata recv() in quel momento.
Nella recente versione del kernel (dal 2.6.37), è possibile utilizzare l'opzione TCP_USER_TIMEOUT funzionerà correttamente. Questa opzione può essere utilizzata per una presa singola.
Infine, è possibile utilizzare la funzione di lettura con il flag MSG_PEEK, che consente di verificare che il socket sia a posto. (MSG_PEEK fa semplicemente capolino se i dati arrivano al buffer dello stack del kernel e non copia mai i dati nel buffer dell'utente.) Quindi puoi usare questo flag solo per verificare che il socket sia a posto senza alcun effetto collaterale.
La domanda riguarda lo scollegamento del cavo Ethernet. – EJP