Tcp / IP parte 7
16 Aprile 2020Tcp / Ip parte 9
16 Aprile 2020
Tcp / IP parte 8
Ovviamente, a livello applicativo, ogni periferica darà ai propri dati una struttura differente.
Questo vuol dire che i dati costruiti per una stampante non possono certo essere mandati a uno scanner.
Il TCP non entra in merito della struttura applicativa dei dati, ma solo alle modalità di trasmissione degli stessi.
Ogni porta TCP è identificata da un numero.
I numeri sotto il 256 sono utilizzati per le cosiddette “porte conosciute”, cioè porte alle quali è stata assegnata una responsabilità ben precisa, mentre quelli al di sopra sono utilizzati per le assegnazioni dinamiche.
Avremo per esempio una porta per i servizi di posta elettronica X.400 chiamata appunto X400 (103) alla quale faranno riferimento tutte le applicazioni che utilizzano tali servizi, oppure le due porte per il trasferimento dei file via FTP, una per il controllo (FTP, 21) e una per i dati (FTP-DATA, 20).
Una lista delle porte conosciute attualmente assegnate è riportata nella RFC 1060.
Eccovele:

Port 1

Port 2

Port 3

Port 4

Port 5

Port 6

Port 7

Port 8

Port 9

Port 10
Mentre in UDP la porta rappresenta un elemento sufficiente alla comunicazione, per cui il protocollo non fa altro che smistare i vari datagrammi nelle code dati (queue) associate alle varie porte .
Una connessione è l’insieme di due punti, detti estremi della connessione (endpoint), ognuno identificato univocamente da due coordinate:
l’indirizzo IP e il numero di porta.
Una connessione è quindi rappresentata da ben quattro identificativi: gli indirizzi IP delle due macchine su cui girano le due applicazioni che si scambiano i dati, e i rispettivi numeri di porta.
È importante capire che l’identificazione della connessione richiede tutti e quattro i valori, per cui la stessa porta con lo stesso indirizzo IP può essere condivisa simultaneamente da più connessioni senza creare alcun problema o ambiguità.
Ecco perché in TCP si pensa in termini di linea dedicata. È come se ci fosse un filo che lega univocamente i due interlocutori.
Ogni interlocutore può avere più connessioni aperte nello stesso momento a partire dallo stesso capo purché non ce ne siano due con la stessa controparte.
Il vantaggio è che una singola applicazione, per esempio di posta elettronica, necessita di una sola porta TCP per fornire servizi a molte macchine contemporaneamente attraverso differenti connessioni che condividono uno stesso estremo.
Va tenuto presente che, anche se UDP e TCP usano gli stessi numeri per le porte, non esiste possibilità di confusione, dato che i pacchetti IP portano con sé l’identificativo del protocollo utilizzato che è ovviamente diverso per i due protocolli.
Affinché la connessione venga stabilita, entrambi gli estremi devono dare la loro autorizzazione. L’aggancio avviene nel seguente modo.
Una delle due applicazioni che si vogliono connettere effettua un’apertura passiva (passive open), cioè informa il suo sistema che è disposta ad accettare una richiesta di connessione. TCP assegna all’applicazione un numero di porta.
L’altra applicazione deve invece effettuare un’apertura attiva (active open), specificando l’indirizzo IP e la porta con la quale si vuole connettere. A questo punto i due livelli TCP stabiliscono la connessione e verificano che tutto sia a posto.
La gestione dei dati: Vediamo adesso come TCP gestisce i dati. Innanzi tutto, come già detto, TCP vede i dati come una sequenza non strutturata di ottetti, cioè byte, detto flusso di dati (data stream).
Questo flusso viene diviso in segmenti ognuno dei quali viaggia di solito in un singolo pacchetto IP. Per aumentare l’efficienza della trasmissione, TCP utilizza una versione particolare del meccanismo a finestre di scorrimento spiegato nella parte 7.
Ricordo che questo meccanismo consiste nel mandare un gruppetto di dati prima di aver ricevuto la conferma di ricezione di ogni singolo pacchetto, in modo da tenere costantemente sotto carico la linea.
Se infatti si dovesse attendere la conferma di ricezione per ogni singolo pacchetto prima di spedire il successivo la linea resterebbe per la maggior parte del tempo inutilizzata.
Si dà insomma fiducia alla rete, partendo dal presupposto che la perdita di dati sia l’eccezione piuttosto che la regola.
Esistono tuttavia due importanti differenze tra il meccanismo base presentato prima e quello più sofisticato utilizzato effettivamente da TCP.
La prima è che l’unità base per i dati non è né il segmento né il pacchetto IP ma il singolo ottetto.
Ogni ottetto viene numerato e TCP mantiene tre puntatori per ogni flusso di dati in uscita:
Uno che separa gli ottetti già spediti e arrivati felicemente a destinazione da quelli di cui non si hanno ancora notizie.
Uno che separa quelli già spediti da quelli che devono ancora essere spediti senza attendere la conferma di ricezione per i precedenti ottetti.
Ed infine uno che separa questi ultimi da quelli che non possono essere spediti fintanto che la finestra non scorre in avanti.
Una serie di informazioni speculari è mantenuta dal destinatario che deve ovviamente ricostruire il flusso di dati nel modo corretto indipendentemente dall’ordine di arrivo dei dati.
Dato che una connessione è full-duplex, TCP manterrà quindi per ogni connessione due finestre di scorrimento, una per i dati in uscita e una per quelli in ingresso: un totale di quattro finestre per connessione considerando entrambi gli estremi. Esiste quindi un’asimmetria rispetto al meccanismo base dove l’unità dati utilizzata nella finestra di scorrimento era la stessa utilizzata nella trasmissione.
Qui TCP utilizza il segmento come unità dati da trasmettere, mentre ragiona in termini di ottetti per quello che riguarda il meccanismo di ritrasmissione.
La seconda differenza è che le dimensioni della finestra di scorrimento non sono fisse ma variano nel tempo in funzione della capacità di ricezione del destinatario.
Ogni conferma di ricezione che ritorna al mittente contiene una soglia di capacità (window advertisement) che contiene il numero di ulteriori ottetti che il destinatario è in grado di ricevere.
In pratica questo meccanismo permette di adattare la finestra di spedizione alle dimensioni del buffer di ricezione.
Si tratta cioè di un meccanismo di controllo del flusso dei dati che limita il numero dei dati in ingresso man mano che il buffer di ricezione si riempie, fino a poter interrompere momentaneamente la trasmissione nel caso che si sia raggiunta la massima capacità di ricezione del destinatario.
Basta infatti che il destinatario mandi una soglia uguale a zero perché il mittente interrompa la spedizione degli ottetti fino all’arrivo di una conferma di ricezione contenente di nuovo una soglia maggiore di zero.
In realtà il mittente non smette del tutto di mandare dati.
Innanzi tutto, se ci sono dati urgenti da spedire, il mittente informa comunque il destinatario di tale necessità trasmettendo un segmento con un indicatore di urgenza al suo interno.
Questo permette al destinatario di prendere delle contromisure per ricevere comunque i dati urgenti, per esempio aumentando le dimensioni del buffer. In secondo luogo, è sempre possibile che la conferma con soglia positiva che dovrebbe far ripartire la trasmissione dei dati vada perduta.
Per questo motivo il mittente prova ogni tanto a far partire un segmento per vedere se per caso il destinatario è di nuovo pronto a ricevere i dati.
Il controllo di flusso: Il controllo del flusso dei dati è un aspetto estremamente importante in un sistema in cui sono collegate macchine anche molto differenti fra loro per dimensioni e capacità di trasmissione .
Per controllo del flusso si intende la possibilità di regolare dinamicamente la quantità di dati che vengono immessi nella rete.
Non solo è importante che il destinatario possa regolare la velocità di spedizione in funzione della sua capacità di ricezione, ma è fondamentale che ogni gateway intermedio possa frenare il flusso dei dati che riceve per evitare di entrare in saturazione.
Il meccanismo appena descritto della soglia di capacità permette di risolvere il primo problema, non il secondo.
Quest’ultimo è detto congestione, ed è estremamente importante perché non tenerne conto vuol dire mandare in tilt la rete.
Lo standard TCP non prevede alcun meccanismo di controllo della congestione, lasciando agli implementatori di tale protocollo il non banale compito di sviluppare una logica capace di evitare questo tipo di problemi.
Per quello che riguarda i segmenti, il fatto che TCP sia libero di dividere il flusso in segmenti può a volte causare problemi dal punto di vista applicativo.
Supponiamo di implementare via TCP/IP un terminale remoto.
Significa che tutte le operazioni effettuate con la tastiera e il mouse su di una macchina (chiamiamola locale) saranno visibili su di un’altra macchina (remota) come se esse fossero state effettuate dalla tastiera e dal mouse della macchina remota.
Sarà possibile vedere lo schermo della macchina remota all’interno di una finestra della macchina locale .
Questo tipo di applicazioni è molto utile per esempio se per un qualche motivo la macchina da controllare non ha una sua tastiera oppure si trova in un locale non generalmente accessibile all’operatore. È evidente che affinché l’applicazione funzioni essa debba lavorare in tempo reale.
Se cioè si preme il tasto T sulla tastiera locale, la lettera T deve apparire immediatamente sullo schermo della macchina remota, e quindi apparire anche all’interno della finestra locale che riproduce tale schermo.
Lo stesso se si fa click sul pulsante di chiusura di una finestra. Ovviamente se TCP fosse libero di accumulare questi comandi per poi spedirli tutti in una volta l’applicazione sarebbe di difficile utilizzo.
Infatti, se l’operatore decidesse di chiudere una finestra dello schermo remoto per accedere un’icona sottostante e TCP non spedisse il comando fintanto che il buffer di partenza non fosse pieno, non sarebbe possibile eseguire l’operazione successiva, cioè aprire l’icona sulla scrivania del sistema.
Per questo motivo TCP prevede la possibilità di forzare la spedizione del buffer (push).
Questo tuttavia non è sufficiente. Se infatti TCP che riceve i dati accumulasse gli stessi nel buffer di ricezione prima di passarli all’applicazione destinataria saremmo punto e da capo.
Per questo motivo, quando un segmento è forzato in uscita, TCP imposta a uno un certo bit nell’intestazione del segmento in modo che questi possa venire riconosciuto e immediatamente passato all’applicazione remota.
Abbiamo detto che il TCP utilizza il metodo della finestra di scorrimento per tenere la rete sempre impegnata al massimo della sua capacità e che esiste un’importante differenza tra il meccanismo generale e quello più sofisticato utilizzato effettivamente dal TCP.
Tale differenza consiste in un’asimmetria rispetto al meccanismo base dove l’unità dati utilizzata nella finestra di scorrimento era la stessa utilizzata nella trasmissione.
Il TCP utilizza il segmento come unità dati da trasmettere, mentre ragiona in termini di ottetti per quello che riguarda il meccanismo di ritrasmissione. Questo comporta una complicazione nella gestione delle conferme di ricezione (acknowledgement).
A causa dell’asimmetria suddetta, la ritrasmissione in caso di mancata ricezione non avviene per segmenti, ma a livello di ottetti.
Questo vuol dire che un segmento può contenere contemporaneamente sia nuovi dati sia una parte dei dati persi in precedenza.
Ovviamente a queste condizioni ha poco senso numerare semplicemente i segmenti e usare questo identificativo nelle conferme di ricezione.
Né è pensabile di usare i datagrammi IP a tale scopo, dato che questi sono generalmente di lunghezza fissa mentre i vari segmenti TCP sono di lunghezza variabile.
L’unico modo per gestire le conferme è quello di ragionare in termini di cursore all’interno del flusso di dati. Come dire “ho ricevuto i primi 300 caratteri della lettera che mi hai spedito”.
Ecco che cosa accade: ogni segmento contiene la posizione dell’area dati del segmento TCP all’interno del flusso di dati.
Tale posizione si chiama numero di sequenza (sequence number) ed è calcolata in byte.
Il destinatario estrae i vari ottetti dai segmenti ricevuti e li ricompone per ricostruire il flusso dei dati, utilizzando i numeri di sequenza per riordinare i vari segmenti.
Questi possono infatti arrivare in qualunque ordine, o essere andati persi.
A questo punto, chi sta ricevendo i dati, avrà ricostruito in modo completo una parte del messaggio originario e si ritroverà alcuni dati in eccesso che non sono contigui alla parte di flusso ricostruito.
Ogni volta che il destinatario riceve un segmento, manda indietro nella conferma di ricezione il numero di sequenza dell’ottetto che si aspetta di ricevere per continuare la ricostruzione, cioè il valore dell’ultimo ottetto della parte contigua ricostruita più uno.
Se vi siete persi le puntate precedenti le trovate qui:
- Tcp / Ip parte 1
La nuova puntata la trovate qui:
