Passa al contenuto principale

A volte netstat mostra una presa che sembra essere bloccata. L'applicazione remota è stata terminata, a volte anche l'applicazione OpenVOS è stata terminata, ma netstat mostra ancora il socket. Questo articolo spiegherà perché questo accade e cosa si può fare al riguardo.

Una breve introduzione agli stati TCP

Se cercate su Google "tcp state diagram" troverete una pletora di immagini, alcune appena leggibili altre piuttosto leggibili. Wikimedia ne ha una codificata a colori molto bella (http://commons.wikimedia.org/wiki/File:TCP_state_diagram.png). Il TCP RFC (793) (http://www.rfc-editor.org/rfc/rfc793.txt) ha un diagramma artistico ASCII e naturalmente spiega gli stati in dettaglio.

Le prese possono bloccarsi quando sono in attesa che l'applicazione locale o l'host remoto faccia qualcosa. Ci sono tre stati in cui questo accade. Nello stato FIN_WAIT_2 la presa è in attesa che l'host remoto chiuda la connessione. Nello stato CLOSE_WAIT è in attesa che l'applicazione locale chiuda il socket e nello stato ESTABLISHED è in attesa che l'host remoto apra la finestra di invio o che l'applicazione locale invii qualcosa. Se lo stack TCP locale ha inviato dati e sta aspettando che l'host remoto riconosca che non può bloccarsi, alla fine si bloccherà, segnalerà un errore all'applicazione locale e chiuderà il socket.

Stato FIN_WAIT_2

Questo è forse il più comune caso di socket bloccato che viene chiamato nel CAC. L'applicazione locale ha chiuso la presa e potrebbe essere terminata. Il motivo tipico per cui le prese sono bloccate in questo stato è che l'applicazione remota è appesa e non legge la sua presa.

Impostando il parametro STCP finwait2 su alcuni N > 0 le prese si chiuderanno dopo che sono state in FIN_WAIT_2 per N secondi. A partire dalle release 14.7.2bg, 14.7.tl1, 15.2.1aa, 15.2.tel.af, 15.3.0bd, 15.3.tel.ag, 16.2.1al, 17.0.0ai, e 17.1 il valore di default è 1200, prima che il valore di default fosse 0 (quindi se si vuole che le prese si chiudano da sole). Si può vedere il valore corrente con la richiesta list_stcp_param analizza_system, si può cambiare il valore con la richiesta set_stcp_param analizza_system. Vedere il manuale OpenVOS System Analysis (R073), disponibile all'indirizzo http://stratadoc.stratus.com, per la documentazione su queste richieste.

Stato CHIUSO_AUTOMOBILE

Questo è il prossimo stato di presa bloccata più comune. Le prese in uno stato CLOSE_WAIT sono in attesa che l'applicazione locale chiuda la presa. Il motivo tipico per cui una presa rimane in questo stato è che l'applicazione non sta più leggendo la presa. Il modo più semplice per chiudere il socket è terminare l'applicazione locale.

Se la terminazione dell'applicazione locale non è un'opzione, l'unica cosa che si può fare è creare un pacchetto con il flag RST (reset) impostato. Questo richiede che si conoscano i numeri di sequenza utilizzati dal socket (disponibili usando la richiesta dump_onetcb analyze_system) e che si disponga di un'utilità su un altro host della sottorete locale che possa costruire e inviare pacchetti IP personalizzati. Queste utilità sono disponibili per sistemi Windows e Linux.

Stato STABILITATO

Poiché il più delle volte netstat mostra le prese nello stato ESTABLISHED come si fa a capire quando la presa è bloccata? Se si dispone di un rapporto che l'host remoto si è bloccato o la rete tra l'host locale e remoto è fallita per più di 10 minuti e l'applicazione locale è in attesa che il telecomando invii qualcosa si può essere abbastanza sicuri che il socket è bloccato. In questo caso il valore della coda di invio (il numero a sinistra dell'indirizzo IP locale) riportato da netstat sarà 0. D'altra parte, se il valore della coda di invio è più grande di 0 e rimane lì si può avere il caso dell'host remoto che pubblicizza una finestra zero.

Nel primo caso, a meno che keep-alive non sia acceso, la presa rimarrà nello stato ESTABLISHED fino al termine dell'applicazione locale. Se keep-alive è acceso, dopo la scadenza del timer keep-alive, STCP invierà una sonda keep-alive. Se la sonda non riceve risposta, verrà ritrasmessa, ma dopo alcuni minuti e diverse ritrasmissioni la connessione verrà terminata. Per default l'interfaccia è impostata su keep-alive, ma anche le prese di default non lo sono. Per impostare keep-alive su un socket l'applicazione deve utilizzare la chiamata di funzione setsockopt. Vedere il manuale OpenVOS STREAMS TCP/IP Programming (R420), disponibile anche su http://stratadoc.stratus.com, per i dettagli. Il tempo keep-alive predefinito è di 2 ore; ciò significa che la prima keep-alive probe viene trasmessa 2 ore dopo la ricezione dell'ultimo segmento TCP dall'host remoto, quindi è necessario essere pazienti. Per chi non è così paziente è possibile regolare il tempo keep-alive e anche il tempo tra le sonde e il numero di sonde con la richiesta set_stcp_parametro all'interno di analyze_system. Sconsiglio di modificare questi parametri senza un'analisi dettagliata.

Se il socket non ha keep-alive set l'unica semplice opzione è quella di terminare l'applicazione che possiede il socket. Se questa non è un'opzione è possibile chiudere il socket inviandogli un segmento con il flag RST impostato..

Per confermare il secondo caso controllare il valore di sndws visualizzato dalla richiesta dump_onetcb analyze_system. Un valore 0 indica una finestra chiusa. Si può anche eseguire packet_monitor per tracciare la connessione e controllare il valore della finestra nell'intestazione TCP in segmenti dall'host remoto. Un valore di "n.a." indica 0.

Voglio sottolineare che questa può essere una condizione recuperabile. Le applicazioni a volte vengono ritardate e lo stack TCP chiude la finestra, quando l'applicazione viene raggiunta lo stack apre la finestra. Tuttavia, nella maggior parte dei casi penso che sia lecito supporre che se l'applicazione non è stata recuperata dopo pochi minuti non lo sarà più. L'eccezione potrebbe essere qualcosa come una stampante che ha finito la carta. Una presa in questo stato può rimanere in questo stato anche se l'applicazione VOS che l'ha creata termina.

Questi socket possono essere puliti impostando tcp_zerowin_abort_interval$ su alcuni N > 0. I socket saranno puliti N secondi dopo la ricezione del prossimo segmento TCP con una finestra zero. Le sonde a finestra vengono inviate ogni 100 secondi per confermare che la finestra di ricezione dell'host remoto è ancora chiusa, quindi nel peggiore dei casi una risposta sarà ricevuta entro 100 secondi. Il valore predefinito di tcp_zerowin_abort_interval$ è zero e suggerisco che rimanga a 0 a meno che non sia necessario pulire un socket. A quel punto suggerisco di impostarlo ad un piccolo valore, diciamo 10 secondi, e una volta che il socket è pulito resettandolo a 0. Penso che questo riduca il rischio di cancellare i socket che sono recuperabili

Per impostare questo valore è necessario utilizzare la richiesta set_longword in analyze_system, quindi ricordate che N sarà in hex. Per esempio, per impostarlo a 10 la richiesta sarebbe:
set_longword tcp_zerowin_abort_interval$ a

© 2024 Stratus Technologies.