Perché le ritrasmissioni TCP bloccano la comunicazione con telecamere industriali, e come isolarle
· Aggiornato il: · Go Komura · TCP, Networking, Bug Investigation, Sviluppo Windows, Telecamera industriale
Nella comunicazione con telecamere industriali e controllo apparati, il sintomo più fastidioso è un collegamento veloce in media ma che occasionalmente si blocca per diversi secondi. Si riproduce raramente e la maggior parte del tempo nulla accade, quindi l’UI, i thread, il GC, l’SDK della telecamera, la NIC e lo switch iniziano tutti a sembrare leggermente sospetti.
Questo articolo tratta un caso in cui la comunicazione TCP tra un host e un’applicazione che controlla una telecamera industriale si bloccava occasionalmente per qualche secondo. Quando abbiamo investigato, il colpevole non era l’applicazione che si congelava, ma TCP in attesa di una ritrasmissione causata da perdita di pacchetto. Inoltre, abilitare la funzionalità timestamps di famiglia RFC1323 (nello scenario degli standard attuali, RFC 7323) ci ha permesso di mantenere al minimo il tempo di attesa in questo sistema.
Nomi dispositivo, configurazioni e numeri sono stati generalizzati, ma il modo di pensare si applica direttamente in pratica.
1. La conclusione prima di tutto (in una riga)
- Una comunicazione TCP che occasionalmente si blocca per diversi secondi può essere causata non dal congelamento dell’app, ma da un’attesa di ritrasmissione a seguito di perdita di pacchetto
- Se una cattura pacchetti mostra
Retransmissioncon un grande gap temporale, e la durata del blocco corrisponde al comportamento delle attese RTO, è abbastanza sospetto - L’opzione TCP timestamps è un meccanismo per RTT measurement e PAWS, e rimuove anche l’ambiguità della misura RTT sulla ritrasmissione
- In questo caso, abilitare la funzionalità timestamps di famiglia RFC1323 ha ridotto il tempo in cui la stima RTO restava obsoleta e conservativa, mantenendo al minimo i blocchi di diversi secondi
- Tuttavia, questo non è magia che fa sparire la perdita in sé. Bisogna ancora rivedere separatamente layer fisico, NIC, switch, dispositivi intermedi, driver e design dei buffer
In breve, se la vera identità di “si blocca occasionalmente per qualche secondo” è un tempo di attesa dentro TCP, sforzarsi solo su retry a livello applicazione manca il bersaglio. È più veloce guardare prima il wire e confermare se ci troviamo in un’attesa di ritrasmissione.
2. Come appare il sintomo
2.1. L’app è viva, ma solo le risposte si bloccano per secondi
La prima parte confusa è che l’applicazione nel complesso non sembra congelata.
- L’UI non è completamente morta
- Il processo non è crashato
- La CPU non è al 100%
- Eppure le risposte ai comandi di controllo della telecamera occasionalmente cadono per diversi secondi
Sintomi come questi sono difficili da distinguere da un deadlock in-app o un loop infinito. Inoltre, nel controllo apparati, un singolo blocco di diversi secondi crea direttamente l’impressione di un fermo linea. Anche se le medie appaiono pulite, la percezione sul campo è considerevolmente peggiore.
2.2. La bassa frequenza rende difficile vederlo solo dai log
Quel che rende fastidioso questo tipo di difetto è la bassa frequenza. Si comporta come una volta all’ora, una volta ogni mezza giornata, o solo quando le condizioni si allineano.
Se lo insegui solo attraverso i log, di solito va così.
- Il log applicativo si ferma su “spedito” e “nessuna risposta tornata”
- Il log lato ricevitore sembra “nulla è arrivato”
- Qualche altro evento capita nello stesso intervallo temporale, sparpagliando i sospettati
In situazioni come questa, provare a ricostruire la causalità solo dai log applicativi è un modo piuttosto affidabile per impantanarsi. È più veloce scendere di un livello, al layer comunicazione.
3. Cosa stava succedendo effettivamente (diagrammi)
3.1. La perdita di pacchetto porta in un’attesa di ritrasmissione
La trama questa volta è semplice. Un pacchetto era perso da qualche parte lungo il percorso, il mittente attendeva un ACK, nessuno arrivava, quindi aspettava lo scadere dell’RTO e poi ritrasmetteva.
sequenceDiagram
participant Host as Host app
participant Net as Rete
participant Cam as Lato telecamera
Host->>Net: Comando di controllo (Seq=N)
Note over Net: Perso qui
Note over Host: Non arriva ACK, quindi attende
Note over Host: Recuperare questa richiesta richiede di attendere l'RTO
Host->>Net: Ritrasmette il comando di controllo
Net->>Cam: Il pacchetto ritrasmissione arriva
Cam-->>Net: ACK
Net-->>Host: ACK
Note over Host: La comunicazione riprende qui
Dal punto di vista dell’applicazione sembra “si è bloccato per qualche secondo”, ma dal punto di vista TCP era semplicemente “non è ancora arrivato un ACK, quindi sto aspettando che scada il timer di ritrasmissione”. È poco appariscente, ma questo tipo di blocco accade continuamente.
Il traffico di controllo in questo caso consisteva principalmente in piccoli scambi richiesta/risposta, e un singolo scambio non aveva una grande quantità di dati non riconosciuti in volo. Di conseguenza, questa era una configurazione in cui l’attesa RTO tendeva a emergere prima che accumulassi abbastanza ACK duplicati per innescare la fast retransmit.
3.2. I blocchi di diversi secondi corrispondevano alla forma dell’RTO
L’attesa di ritrasmissione TCP, sebbene vari per implementazione, si comporta in modo conservativo. Sotto RFC 6298, l’RTO iniziale ha una baseline di 1 secondo; se il valore calcolato è inferiore, viene arrotondato a 1 secondo, e quando scade un timeout, l’RTO raddoppia.
flowchart LR
A[Perdita pacchetto] --> B[Non arriva ACK]
B --> C[Attendi l'RTO]
C --> D[Ritrasmetti]
D --> E{ACK tornato?}
E -- Si --> F[Comunicazione riprende]
E -- No --> G[Raddoppia l'RTO]
G --> C
Quindi anche in situazioni in cui vorresti risolvere in qualche centinaio di millisecondo, in condizioni avverse le attese possono apparire come 1 secondo, 2 secondi, 4 secondi. Il “si blocca occasionalmente per qualche secondo” in questo caso si allineava piuttosto naturalmente con quella forma.
4. Cosa abbiamo guardato durante l’indagine
4.1. Per prima cosa escludere cause di stallo interne all’app
Piuttosto che saltare subito a incolpare TCP, abbiamo prima escluso le tipiche cause lato applicazione.
| Cosa abbiamo controllato | Perché abbiamo guardato | Conclusione in questo caso |
|---|---|---|
| Thread UI / worker thread | Verificare blocchi o attese reciproche | Non la causa principale |
| Uso CPU | Verificare ritardi di elaborazione sotto carico | Non al 100% anche durante i blocchi |
| GC / pressione memoria | Verificare pause | La forma delle durate di blocco non corrispondeva |
| Chiamate SDK telecamera | Verificare attese dentro l’SDK | Non corrispondevano ai ritardi sul wire |
| Cattura pacchetti | Verificare ritrasmissioni al layer comunicazione | È qui che è emersa la causa |
La cosa importante qui è non scegliere il colpevole basandosi solo sui timestamp dei log applicativi. Nelle applicazioni di controllo apparati, un’attesa a livello superiore a volte è solo il riflesso di un’attesa a livello inferiore.
4.2. Confermare le ritrasmissioni con una cattura pacchetti
Quando abbiamo preso una cattura pacchetti, vedemmo TCP Retransmission nella finestra temporale del blocco, e inoltre che nessun ACK era tornato subito prima.
Questi sono i punti da guardare.
- Stesso
Seqviene ritrasmesso? - Il gap temporale fino alla ritrasmissione corrisponde alla durata del blocco?
- Sembra un’attesa per scadenza RTO piuttosto che
Dup ACKoFast Retransmission? - La connessione problematica appare sempre come lo stesso
tcp.stream?
Quando questi si allineano, “TCP sta aspettando una ritrasmissione” diventa molto più probabile di “l’app è congelata”.
4.3. Guardare le opzioni TCP negoziate
La prossima cosa che abbiamo guardato era il SYN / SYN-ACK all’apertura della connessione. I timestamp vengono negoziati nel three-way handshake TCP, quindi se TSopt non appare lì, non è usato su quella connessione.
sequenceDiagram
participant Host as Host
participant Cam as Lato telecamera
Host->>Cam: SYN + TSopt ?
Cam-->>Host: SYN/ACK + TSopt ?
Host->>Cam: ACK
Note over Host,Cam: Solo dopo avernegoziato qui TSopt può essere usato sui segmenti successivi
Se giochi con le impostazioni OS senza guardare questo, finisci con un altro incidente poco appariscente: “ne sono sicuro di averlo abilitato, ma non ha effetto”. I fatti sul wire sono più forti dei valori configurati.
5. Perché i timestamp RFC1323 aiutano
In pratica la gente ancora chiama questo “i timestamp RFC1323”, ma lo standard corrente è RFC 7323. Questo articolo segue l’uso consueto e scrive RFC1323, intendendo l’opzione TCP timestamps.
5.1. I timestamp esistono per RTTM e PAWS
L’opzione timestamps di TCP viene usata principalmente per due scopi.
- RTTM (Round-Trip Time Measurement)
- PAWS (Protect Against Wrapped Sequences)
Quel che ha aiutato in questo caso era il lato RTTM. Facendo eco del TSval di un segmento trasmesso nel TSecr dell’ACK, il peer può misurare RTT in modo più fine e accurato.
5.2. Rimuovono l’ambiguità della misura RTT sulla ritrasmissione
Una volta che avviene una ritrasmissione, senza timestamp diventa ambiguo se “questo ACK è per la trasmissione originale o per la ritrasmissione”. Questo è il punto cui si occupa l’algoritmo di Karn.
RFC 6298 dice che non si deve prendere un campione RTT da un segmento ritrasmesso. Il motivo è che non si riesce a dire a quale trasmissione corrisponda l’ACK. Con l’opzione timestamps, però, questa ambiguità svanisce: guardando il TSecr nell’ACK che arriva, si può identificare quale segmento, con quale TSval, è effettivamente passato.
sequenceDiagram
participant Host as Sender
participant Cam as Receiver
Host->>Cam: Seq=N, TSval=1000
Note over Host,Cam: Questo segmento è perso
Note over Host: Non arriva ACK, quindi attende
Host->>Cam: Ritrasmetti Seq=N, TSval=2000
Cam-->>Host: ACK, TSecr=2000
Note over Host: Può dire a quale trasmissione corrisponde
Questo è il nucleo del miglioramento in questo caso.
5.3. Perché potevamo stringere il tempo di attesa in questo caso
In questo caso, la perdita di pacchetto avveniva di tanto in tanto, e ogni occorrenza tendeva a spingere le stime RTT / RTO verso il lato conservativo. Abilitare i timestamp rende più facile aggiornare la stima RTT anche in scenari che coinvolgono ritrasmissioni, il che limita il tempo in cui la stima RTO resta gonfiata e obsoleta.
In altre parole, quello che abbiamo fatto non è magia che rende TCP più veloce, ma ridurre il tempo in cui TCP continua a guardare e aspettare più del necessario.
Ovviamente, RFC 7323 non sostiene che “più campioni RTT risolvono tutto pulitamente”. Il grado in cui aiuta l’ottimizzazione RTO è limitato sotto certi aspetti. Tuttavia, il fatto che rimuova l’ambiguità sulla ritrasmissione può aiutare abbastanza naturalmente in un sistema come questo.
Ci sono cavilli.
- Parte di questo dipende dall’implementazione dello stack TCP
- I timestamp da soli non fanno sparire la perdita di pacchetto in sé
- Se il layer fisico o i dispositivi intermedi sono in colpa, la causa radicale sta altrove
- SACK, driver NIC, impostazioni offload e problemi lato switch vanno esaminati separatamente
Detto questo, in un sistema come questo — dove “la perdita non è zero” ma “quel che fa veramente male è l’attesa di diversi secondi” — può essere abbastanza efficace.
6. Cosa abbiamo fatto effettivamente
6.1. Abilitare i timestamps
Come contromisura, ci siamo assicurati che l’opzione timestamps potesse essere negoziata su entrambe le estremità della connessione. Sui sistemi Windows questa è a volte trattata come l’opzione RFC 1323, ed è influenzata da impostazioni OS e di rete.
In pratica, però, quel che conta non è “è abilitata nelle impostazioni” ma “TSopt è effettivamente presente sui pacchetti SYN / SYN-ACK sul wire”. Questo è veramente vero.
6.2. Verificare TSopt in SYN / SYN-ACK
Dopo averla abilitata, abbiamo verificato tre cose.
- Il SYN della connessione in questione porta TSopt?
- Anche il SYN/ACK lato ritorna TSopt?
- I segmenti di dati successivi e gli ACK continuano a portare TSopt?
Solo quando queste sono conferme si può dire “i timestamp sono effettivamente usati su quella connessione”.
6.3. Dove guardare se ancora non aiuta
Anche con i timestamp abilitati, il miglioramento può essere lento in casi come questi.
- Il tasso di perdita in sé è alto
- Un dispositivo intermedio rompe, scarta o altera le opzioni TCP
- C’è un problema separato intorno a NIC / driver / offloading
- L’applicazione appende tutto a una singola chiamata sincrona, così una sola attesa sembra uno stallo totale
- La causa primaria non è TCP, ma uno stallo di elaborazione sul lato telecamera o una coda intasata dentro il dispositivo
Quindi è più chiaro procedere con le contromisure in questo ordine.
- Conferma prima l’attesa di ritrasmissione sul wire
- Controlla se TSopt viene negoziato
- Abilita i timestamps e misura il delta di miglioramento
- Se i problemi restano, affronta separatamente la sorgente di perdita e il design applicativo
7. Cosa controllare in Wireshark
Ecco display filter utili per l’isolamento.
tcp.stream eq <target stream>
tcp.analysis.retransmission
tcp.analysis.fast_retransmission
tcp.analysis.lost_segment
tcp.options.timestamp.tsval
tcp.options.timestamp.tsecr
Ci sono alcuni trucchi per leggere i risultati.
- Restringi alla connessione target con
tcp.stream - Visualizza
Time delta from previous displayed packetper vedere direttamente i secondi di stallo - Conferma se
Retransmissionappare nel momento problematico - Conferma se TSopt viene negoziato nel SYN / SYN-ACK all’apertura della connessione
- Controlla se
TSecrviene restituito negli ACK
Quando si correlano log con pacchetti, fai attenzione anche all’offset tra orologio applicazione e orologio della cattura. Se sono sfasati, tendi ad attribuire la colpa a un evento non correlato.
8. Una guida decisionale approssimativa
| Sintomo | Primo sospetto | Prima azione |
|---|---|---|
| Si blocca occasionalmente per diversi secondi | Attesa RTO di TCP | Conferma ritrasmissioni e gap temporali nei pacchetti |
| Si blocca quasi allo stesso istante ogni volta | Attese in-app, elaborazione lato dispositivo, timeout fissi | Guarda thread, chiamate SDK, log dispositivo |
| Degrada solo sotto alto carico | CPU, GC, code intasate | Guarda CPU, interrupt, memoria, lunghezza code |
| Cattivo su molte connessioni contemporaneamente | Layer fisico, switch, dispositivi intermedi | Guarda NIC, cavi, statistiche porte, log dispositivi intermedi |
| Ho cambiato impostazioni ma non è cambiato nulla | L’opzione TCP non viene negoziata | Ricontrolla SYN / SYN-ACK |
Quell’ultima riga è genuinamente comune. La soddisfazione di aver modificato un’impostazione e il fatto che venga usata sul wire sono due cose diverse.
9. Riassunto
Punti chiave questa volta:
- “Si blocca occasionalmente per diversi secondi” può essere l’attesa di ritrasmissione di TCP, non l’app congelata
- Se la durata del blocco corrisponde al comportamento delle attese RTO e si vede
Retransmission, sei su una buona pista - L’opzione TCP timestamps è un meccanismo per RTTM e PAWS, e rimuove l’ambiguità della misura RTT sulla ritrasmissione
- In questo caso, abilitare la funzionalità timestamps di famiglia RFC1323 ha limitato il tempo in cui l’RTO restava eccessivamente conservativo
Approcci da evitare:
- Scegliere il colpevole per un blocco di comunicazione solo dai log applicativi
- Guardare solo le impostazioni OS senza guardare i pacchetti effettivi
- Assumere che abilitare i timestamps eliminerà anche la causa della perdita
Approcci che funzionano in pratica:
- Guarda prima il wire
- Conferma la forma delle ritrasmissioni e dei tempi di attesa
- Conferma la negoziazione TSopt
- Anche dopo il miglioramento, affronta separatamente la sorgente di perdita e il design applicativo
In altre parole, con questa classe di difetti, “individuare dove sta aspettando” viene prima di “renderlo più veloce”. Solo non perdere questo accorcia considerevolmente l’indagine.
10. Riferimenti
- RFC 1323 - TCP Extensions for High Performance
- RFC 7323 - TCP Extensions for High Performance
- RFC 5681 - TCP Congestion Control
- RFC 6298 - Computing TCP’s Retransmission Timer
-
[Description of Windows TCP features - Windows Server Microsoft Learn](https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/description-tcp-features)
Articoli correlati
Articoli recenti con gli stessi tag per approfondire argomenti vicini.
Costruire una base di test del percorso di fallimento Windows con Application Verifier
Cos'è Application Verifier, organizzato insieme a come costruire una base di test del percorso di fallimento Windows utilizzando Handles,...
Indagine sugli arresti anomali a lungo termine di un'app per fotocamere industriali: la perdita dell'handle (parte 1)
Come esaminare un'app Windows che si arresta improvvisamente in modo anomalo dopo un funzionamento prolungato, utilizzando un caso di stu...
Icone nella system tray e notifiche toast nelle app Windows — le insidie di NotifyIcon e come scegliere l'AppNotification giusta
Una guida pratica per mantenere un'applicazione Windows aziendale residente nella system tray (area di notifica) e avvisare l'utente tram...
Fino a quando funzioneranno le applicazioni VB6? — Lo stato del supporto al runtime e un percorso pratico verso la migrazione a .NET
Fino a quando continueranno a funzionare le applicazioni VB6? Questo articolo chiarisce l'asimmetria tra la politica di supporto del runt...
Era giapponese, festività e date di chiusura nelle applicazioni aziendali — progettazione resiliente ai cambi di era, JapaneseCalendar e calcolo dei giorni lavorativi nella pratica
Mostrare «Reiwa 8» su un documento, calcolare i giorni lavorativi escludendo le festività, pagare entro la fine del mese successivo dopo ...
Argomenti correlati
Queste pagine collocano l’argomento in un contesto più ampio di servizi e decisioni.
Argomenti tecnici Windows
Portale su sviluppo Windows, analisi dei problemi e valorizzazione delle risorse esistenti.
Analisi dei bug e guasti di lunga durata
Errori intermittenti, diagnosi delle comunicazioni, crash prolungati e test dei percorsi di errore.
Casi di studio correlati
Questi casi mostrano un approccio simile all’analisi, alla definizione delle priorità o alla riprogettazione.
Come abbiamo isolato blocchi della comunicazione di diversi secondi
Caso di studio su un raro blocco della comunicazione, separato tra attesa della ritrasmissione e condizioni lato sistema operativo.
Servizi collegati all’argomento
L’articolo è direttamente collegato ai servizi seguenti.
Analisi dei bug e delle cause
Questo articolo parla di isolare un difficile stallo di comunicazione usando pacchetti ed evidenze, il che coincide esattamente con il nostro servizio di bug investigation e root cause analysis.
Sviluppo di applicazioni Windows
Si collega anche a consulenze per rivedere il design di comunicazione e il monitoraggio dal lato implementazione, per app Windows che integrano apparati.
Domande frequenti
Domande che ricorrono nelle consulenze sull’argomento dell’articolo.
- Perché la mia connessione TCP si blocca occasionalmente per diversi secondi?
- Una causa comune è l'attesa di ritrasmissione a seguito di perdita di pacchetto, non un congelamento dell'applicazione. Quando un pacchetto viene perso, il mittente attende un ACK che non arriva e deve aspettare il retransmission timeout (RTO) prima di rispedire. Sotto RFC 6298, l'RTO iniziale ha una baseline di 1 secondo e raddoppia a ogni timeout, quindi in condizioni avverse le attese appaiono come 1, 2, poi 4 secondi — esattamente lo schema di "blocchi occasionali di qualche secondo".
- Come confermo in Wireshark che le ritrasmissioni TCP causano i blocchi?
- Restringi alla connessione con il filtro tcp.stream, poi cerca tcp.analysis.retransmission nella finestra temporale del blocco. Cerca lo stesso sequence number ritrasmesso, un gap temporale prima della ritrasmissione che corrisponde alla durata del blocco, e la forma di attesa per scadenza RTO piuttosto che fast retransmission. Controlla anche SYN/SYN-ACK per vedere se l'opzione timestamps (TSopt) è stata negoziata, e visualizza il time delta dal pacchetto precedente per vedere direttamente i secondi di stallo.
- Cosa fa effettivamente l'opzione TCP timestamps (RFC 1323)?
- L'opzione timestamps serve a due scopi: RTTM (Round-Trip Time Measurement) e PAWS (Protect Against Wrapped Sequences). Per gli stalli di ritrasmissione, conta il lato RTTM: il peer fa eco del TSval del mittente nel TSecr dell'ACK, rimuovendo l'ambiguità se l'ACK risponde alla trasmissione originale o alla ritrasmissione. Questo permette a TCP di continuare ad aggiornare la stima RTT anche in scenari con ritrasmissioni, limitando il tempo in cui l'RTO resta gonfiato eccessivamente conservatore. Lo standard corrente è RFC 7323, anche se si usa abitualmente il nome RFC 1323.
- Abilitare i timestamp TCP risolve la perdita di pacchetto?
- No. Abilitare i timestamp non è magia che fa sparire la perdita in sé — riduce solo il tempo in cui TCP continua ad attendere più del necessario. Se il tasso di perdita è alto, o la causa radicale risiede nel layer fisico, driver NIC, impostazioni offload, switch o dispositivi intermedi che alterano le opzioni TCP, quelle vanno affrontate separatamente. Verifica anche sul wire che TSopt appaia effettivamente in SYN e SYN-ACK, perché un'impostazione abilitata ma mai negoziata non ha effetto.
Profilo dell’autore
Pagina di presentazione dell’autore dell’articolo.
Go Komura
Rappresentante di KomuraSoft LLC
Specializzato nello sviluppo di software Windows, nella consulenza tecnica e nell’analisi dei malfunzionamenti, soprattutto nei progetti con sistemi esistenti e guasti difficili da riprodurre.