se un pacchetto TCP viene parzialmente riconosciuto, come reagirà il meccanismo di ritrasmissione?


12

se un client tcp invia un pacchetto, con numero di sequenza compreso tra 10000 e 20000, a un server tcp. il tcp risponderà con un ACK con seq_ack 20001.

se intercetto il pacchetto TCP dal client e divido il pacchetto in 2 segmenti tcp, uno con seq da 10000 a 15000 e l'altro con seq da 15001 a 20000. E poi questi 2 segmenti TCP vengono inviati al server TCP. Supponiamo che il secondo segmento sia perso nel percorso. Il server TCP risponderà a un ACK con seq_ack 15001.

Ora poiché il client TCP invia un pacchetto integrale con seq da 10000 a 20000, ma ottiene un ACK con 15001, dal punto di vista del client, questo è strano. Come reagirà? In teoria, il client dovrebbe ritrasmettere i byte dal seq 15001 al 20000, ovvero il client trasmetterà nuovi pacchetti dal seq 15001. Ma che ne dite della pratica, nell'implementazione dello stack TCP, è la stessa della teoria?

Penso che nel buffer di invio TCP, quando viene inviato un segmento tcp, il segmento rimane lì fino all'ACK. Quando arriva l'ACK, questi byte per il segmento vengono cancellati dal buffer. C'è un puntatore nel buffer di invio, quando arriva un ACK, il puntatore punta alla posizione in cui ack_seq corrisponde. I byte che si trovano sotto ack_seq vengono cancellati. In questo modo, non è necessario ritrasmettere l'intero segmento?

Risposte:


8

Questo si chiama riconoscimento selettivo ed è già incluso nella specifica TCP definita in RFC 2018 . Ciò consentirebbe al client di inviare nuovamente solo i byte da 15001 a 20000 (dal momento che si trovano in pacchetti / segmenti diversi se li avessi divisi come dici tu), ma, cosa più interessante, consente persino riconoscimenti fuori ordine.

Da RFC 2018:

Quando riceve un ACK contenente un'opzione SACK, il mittente dei dati DOVREBBE registrare il riconoscimento selettivo per riferimento futuro. Si presume che il mittente dei dati abbia una coda di ritrasmissione che contiene i segmenti che sono stati trasmessi ma non ancora riconosciuti, in ordine di numero progressivo.

Il supporto nonSACK è richiesto dalla specifica TCP. Se il client o il server non supportavano il riconoscimento selettivo, tutti i byte da 10000 a 20000 dovrebbero essere ritrasmessi.

Nell'implementazione dello stack TCP, è lo stesso della teoria?

Di solito SACK è supportato, poiché le prestazioni, l'efficienza e i guadagni di latenza sono significativi, specialmente in una rete come Internet.

In effetti, tuttavia, questi presupposti dovrebbero essere validi anche se si manipolano manualmente i pacchetti come indicato. Come da RFC 793 , come minimo, l'intera finestra di dati dovrà essere ritrasmesso, ma il ricevitore non sa che i dati ricevuto le sia almeno valida . Per i dettagli sull'implementazione, Sezione 3.3 - Numeri di sequenza di RFC 793.

Per una descrizione dell'intero processo sia con che senza supporto di riconoscimento selettivo, vedere questo articolo (che include alcuni diagrammi molto utili).


è un po 'strano per me, perché TCP è un protocollo basato sul flusso e orientato ai byte. Perché dovrebbe ritrasmettere l'intero segmento? Mi sembra che TCP senza SAKC sia un protocollo di flusso orientato al segmento, ma TCP con Sack è realmente orientato al byte. Penso che la RFC non si occupi specificamente di questo.
misteri del

come lo stack TCP gestisce il suo buffer di invio, è lo stesso di quello che ho scritto nella domanda aggiornata.
misteri del

@misteryes questo articolo delinea il processo (anche con alcuni grandi diagrammi!).
Svolta del

Nel link che hai raccomandato, sembra che l'autore discuti ancora il problema in modo orientato al segmento, non in modo orientato al byte reale. No?
misteri del

1
Conoscevo SACK prima di pubblicare questa domanda. All'inizio non credo che SACK abbia qualcosa a che fare con questa domanda. Secondo me, se TCP non è orientato ai byte ma orientato al segmento, anche SACK dovrebbe essere lo stesso. La differenza tra SACK abilitato e SACK disabilitato è che con SACK, TCP consente un foro di sequenza in ack_seq. Ma ho pensato che il foro della sequenza corrispondesse a un segmento. mentre secondo il tuo detto, il buco può essere metà / parte di un segmento.
misteri del

3

Le dimensioni del segmento possono (e fare) cambiare nel corso della vita di una connessione. Fortunatamente, TCP non ha bisogno di registrare la dimensione del segmento con cui i singoli pacchetti sono stati inviati in precedenza. Pertanto, farà quanto segue:

  1. Ogni volta che arriva un ACK, far avanzare il puntatore al primo byte non riconosciuto di conseguenza e scartare qualsiasi buffer ora non necessario.
  2. Quando si presenta la necessità di ritrasmissione (ritrasmissione rapida o timeout; NON immediatamente dopo la ricezione del primo ACK!), Rinvia nella dimensione del segmento attualmente valida a partire dal puntatore al primo byte non riconosciuto.

Entrambe le operazioni vengono eseguite indipendentemente dalla dimensione del segmento in cui questi byte sono stati originariamente inviati. Quindi la teoria dovrebbe corrispondere alla maggior parte delle implementazioni.

Consentitemi di fornire alcuni retroscena per spiegare:

TCP utilizza byte o segmenti? All'applicazione, TCP espone un'interfaccia di flusso di byte. Inoltre, tutti i campi dell'intestazione e le variabili interne sono in byte. Tuttavia, per trasmettere informazioni, TCP le suddivide in segmenti, poiché l'invio di byte uno a uno sarebbe piuttosto dispendioso :-). L'uso dei contatori di byte ovunque ha il vantaggio che la dimensione del segmento non deve rimanere costante per tutta la durata della connessione:

  • Sono state introdotte opzioni, ad esempio il trasporto di un SACK su una ritrasmissione (le implementazioni reali lo incontreranno raramente, se non del tutto)
  • L'MTU percorso cambia, ad es. Un collegamento lungo il percorso cambia in un MTU inferiore oppure viene sollevato il collegamento MTU collo di bottiglia. Ciò accade quando vengono stabiliti tunnel (VPN, PPPoE) o quando il protocollo di routing seleziona un collegamento MTU diverso. Ciò accade in IPv4 con il set Non frammentare (vero per la maggior parte dei TCP moderni); sempre in TCPv6).

A proposito: SACK non è la risposta qui, poiché il ricevitore (tipicamente) utilizzerà SACK solo se riconosce un buco nel flusso di byte (cioè, se un pacchetto si è perso ma è arrivato un pacchetto successivo).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.