PROTOCOLLO TCP\IP

         

 

 

iL PROTOCOLLO TCP/IP - 1° PARTE

Miliardi di bit viaggiano ogni giorno sulla Rete. Vi siete mai chiesti come fanno ad arrivare al corretto destinatario? In questo articolo, primo di una serie vi presentiamo "la suite di protocolli TCP/IP" cioè le regole utilizzate per la trasmissione su Internet. Non è certo fondamentale sapere come funziona uno spinterogeno o un albero di trasmissione per guidare un'automobile. Analogamente, al giorno d'oggi, non serve sapere come funziona un computer per poterlo utilizzare. La tecnologia ci scherma sempre di più dal come una cosa funziona spostando l'attenzione sul cosa fare per utilizzarla. Così, quella che era una volta tecnologia per un'élite abbastanza ristretta di studiosi, ricercatori e studenti, è oggi una realtà a disposizione di tutti. Non solo è diventato semplice navigare nella Ragnatela, ma oggi chiunque può facilmente costruirsi le sue pagine e agganciarle a uno dei tanti siti Web che ospitano pagine private. Non c'è più neanche bisogno di conoscere l'HTML, grazie alla proliferazione di editor HTML commerciali e di pubblico dominio. In quanto ai risultati estetici, beh, lì non c'è programma che tenga.

Ma cosa c'è sotto a tutto ciò? Per chi è ancora e nonostante tutto interessato a capire come funzionano le cose, e se vogliamo anche per coloro ai quali la cosa non interessa per niente, ma hanno qualche minuto per leggere un paio di paginette e poi, chissà, potrebbe sempre tornare utile... insomma, per chi vuole, ecco a voi il "TCP/IP, questo sconosciuto".

Il nome

Il nome completo è TCP/IP Internet Protocol Suite, ed è un insieme di protocolli di trasmissione di cui i due principali sono appunto il TCP (Transmission Control Protocol) e l'IP (Internet Protocol). Ma che cosa è esattamente un protocollo? Essenzialmente è una serie di regole per comporre dei messaggi e per far sì che essi possano essere scambiati tra due macchine. Non stiamo parlando solo di computer. Anche una centrale telefonica meccanica può ricadere in questa definizione. Un protocollo può contenere regole estremamente dettagliate, come quelle che identificano il significato di ogni singolo bit nella costruzione di un messaggio, oppure fornire uno scenario di alto livello, come per esempio definire come avviene il trasferimento di un file da un computer a un altro. Fondamentalmente un protocollo sta alla trasmissione dati come un linguaggio di alto livello quale il C++ sta alla programmazione. Infatti, un linguaggio di programmazione comprende sia regole estremamente dettagliate che devono essere seguite alla lettera - guai a dimenticare anche un solo punto e virgola alla fine di un'istruzione C++ - sia strutture di alto livello che vanno costruite nel modo corretto, pena errori nella struttura logica del programma.

Una generica architettura di trasmissione è formata da una torre a più piani, dove ogni piano rappresenta una precisa responsabilità nella trasmissione dei messaggi. Alla base della torre sta la porta di accesso alla rete fisica, che potremmo pensare come una rete di strade. Ogni piano prende il messaggio che arriva dal piano superiore, lo mette in una busta con alcune informazioni aggiuntive, e lo passa come messaggio al piano inferiore.

Le regole di comunicazione tra i vari piani sono dette interfacce. Il messaggio risultante, formato da tante buste una dentro l'altra, viene immesso nella rete dalla porta che si trova alla base della torre. Una volta arrivato al piano terreno infatti, esso viene trasportato alla torre di destinazione e da qui risale un piano dopo l'altro fino all'ultimo piano, detto anche livello applicativo. Ogni piano della torre di destinazione apre solo la busta che gli compete e usa le informazioni aggiuntive per recapitare la busta successiva al piano superiore. Le informazioni aggiuntive rappresentano il protocollo di comunicazione. Ogni piano comunica quindi solo con il piano corrispondente

 

IL PROTOCOLLO TCP/IP - 2° PARTE

Torniamo al sistema a pacchetti. Per trasferire dati da un sistema a un altro ogni sistema ha un nome unico ben definito. Non esistono cioè due sistemi con lo stesso nome, anche se in reti diverse, indipendentemente da quale è il nome locale di un sistema nella sua rete di appartenenza. All'interno di ciascuna rete, i vari computer usano la tecnologia hardware e software specifica di quella rete. Tuttavia, grazie a questo strato intermedio di software, le varie applicazioni hanno una visione unica e globale del sistema interconnesso di reti, detto appunto internet. Notate la "i" minuscola. Il concetto di internet è infatti quello appena descritto. Viceversa Internet con la "I" maiuscola, identifica quel sistema di reti, basato sull'architettura internet, che viene detto anche Connected Internet.

La connessione tra due reti avviene attraverso macchine opportune che sono collegate fisicamente a entrambe le reti, e hanno la responsabilità di far passare i vari pacchetti da una rete all'altra e viceversa. Tali macchine sono dette internet gateway, o anche IP router. Sono loro il vero elemento portante di una internet. Ogni router non solo deve sapere che determinati pacchetti vanno passati da una rete a un'altra, ma deve passare dall'altra parte anche pacchetti destinati a ulteriori reti connesse attraverso altri router. Essi però ragionano solo in termini di reti, non di destinazione finale. A un router non interessa chi è effettivamente il destinatario di un pacchetto, ma solo a quale rete appartiene. Questo semplifica molto l'implementazione di un router. Alla base del meccanismo dei router c'è l'indirizzo IP, o IP address.

Ogni cosa che conosciamo ha un nome. Cane, casa, auto, e via dicendo. Se ci interessa specificare meglio ciò di cui stiamo parlando, possiamo assegnare un nome anche a un sottogruppo di cose. Così abbiamo che i cani bassotti sono alquanto diversi dai San Bernardo, una catapecchia non è certo una villa, e una Ferrari costa un po' più di una Cinquecento. Se poi dobbiamo identificare una cosa in modo chiaro e univoco, è necessario assegnarle un nome che solo quella cosa ha. Già un nome come Mario Rossi non va bene, perché non è unico, e comunque, anche se scegliessimo oggi un nome veramente strano e originale, non avremmo la garanzia in futuro di non ritrovarci con un caso di omonimia. Ecco allora le targhe per le automobili, i codici fiscali per le persone, i numeri di telefono, e via dicendo. Ognuno di questi nomi ha tre caratteristiche. La prima è che esiste un organo competente centrale che li assegna, proprio per garantirne l'univocità. La seconda, è che hanno una struttura a sottogruppi. Esistono cioè degli elementi che garantiscono l'univocità a un certo livello, all'interno del quale esiste una certa libertà di scelta, e così via, livello dopo livello. Per esempio, il codice fiscale viene costruito in modo che un uomo e una donna non possano mai avere lo stesso codice, anche se fossero nati lo stesso giorno, nella stessa città e si chiamassero nello stesso modo. Similmente, i numeri di telefono di due città diverse si distinguono per il prefisso e se queste si trovano anche in stati diversi, per il prefisso internazionale.

Affinché internet possa rappresentare un sistema universale di comunicazione, permetta cioè di far comunicare qualunque macchina connessa a una delle sue reti con una qualsivoglia altra macchina connessa alla stessa o a un'altra rete, è necessario fornire ogni macchina di un nome unico a livello globale. Internet fornisce ogni sistema di un nome, che identifica il sistema stesso, di un indirizzo, che mi dice dove si trova il sistema, e di un cammino, che mi dice come raggiungere il sistema. Ogni macchina connessa a una rete è detta host, nella terminologia internet. Lo stesso termine ha significati differenti in altri contesti informatici, come per esempio in quello client/server, o nel caso di mainframe. Attenzione a non fare confusione quindi. In internet un host può essere anche un vecchio 8088 con 640K di RAM e 10M di disco fisso.

Gli indirizzi IP

L'indirizzo, o IP address, è un campo composto da 32 bit. I primi bit permettono di distinguere 5 forme standard identificate da una lettera del alfabeto, e dette classi. Le prime tre classi dell'IP address contengono sia l'indirizzo di una rete (netid), sia quello di una macchina nella stessa (hostid). In realtà l'indirizzo non identifica necessariamente una macchina, ma una connessione alla rete. Per esempio, un router ha almeno due indirizzi, avendo connessioni ad almeno due reti. Questo in quanto un router appartiene a entrambe le reti, e quindi sono necessari due indirizzi dato che un IP address ha posto per un solo indirizzo di rete. Se l'indirizzo dell'host è 0, allora l'IP address si riferisce alla rete stessa. Se viceversa tutti i bit riservati all'indirizzo dell'host sono 1, allora l'indirizzo viene utilizzato per identificare tutti gli host della rete (broadcasting). Uno speciale indirizzo formato da 32 bit posti a uno è chiamato local network broadcast address e serve solo in casi molto particolari. Il concetto di broadcasting è quello della diffusione a tutto raggio, un po' come fa un'emittente radiofonica. In generale internet interpreta i campi formati da tutti uno come all, cioè "tutti", mentre quelli formati da tutti zero come this, cioè "questo", "qui". Questo per quanto riguarda le classi A, B e C. La classe D è usata per un particolare tipo di distribuzione dei dati detto multicasting. La classe E è riservata a usi futuri. Dato che specificare ogni singolo bit di un indirizzo IP sarebbe alquanto poco pratico e di scarsa leggibilità, la convenzione è quella di leggere ogni ottetto, cioè ogni gruppo di 8 bit, come un intero, e di separare i quattro ottetti con un punto. Oltre a i casi speciali già descritti, l'indirizzo di classe A 127.0.0.0 è riservato per un particolare processo di test che rimanda indietro i dati al mittente senza propagarli nella rete.

Uno dei vantaggi di questo schema è la possibilità da parte dell'organismo centrale che assegna gli indirizzi (Network Information Center) di delegare ai responsabili delle singole reti l'assegnazione di una parte dell'indirizzo all'interno della rete stessa. La cosa avviene un poco come con i numeri di telefono. A livello internazionale ogni stato ha il suo prefisso internazionale. Per esempio, per l'Italia, è 39. All'interno ogni stato divide il paese in aree geografiche a cui assegna un ulteriore codice. Per esempio, Roma è identificata dal 6, Milano dal 2, Firenze da 55, e così via. All'interno poi della provincia o della città possono essere definite ulteriormente sottoaree a cui si assegnano due, tre o quattro cifre. Per esempio 529 oppure 7054. Infine ogni telefono in tali aree avrà il suo numero. Così, se Mr. Smith deve chiamare dagli Stati Uniti il signor Mario Rossi abitante all'EUR, a Roma, comporrà per esempio il numero 011.39.6.529.4467. In questo caso lo 011 serve per uscire dagli USA, un po' come il nostro 00.

Analogamente in internet i numeri di classe C sono assegnati alla piccole reti, quelle cioè con meno di 256 host, quelli di classe B alle reti con al massimo 65536 host, e quelli di classe A alle reti con oltre 16 milioni di host. Ogni rete decide poi come suddividere gli indirizzi che gli sono stati riservati al suo interno come meglio crede. Ovviamente, una internet privata non ha la necessità di seguire queste regole, né a utilizzare indirizzi assegnati dal NIC, ma il non farlo potrebbe impedire in futuro la connessione alla TCP/IP Internet.

Dato che l'indirizzo può essere a volte abbastanza ostico da ricordare, è possibili associare a ogni host anche un nome, che può essere utilizzato come mnemonico per un IP address, e la cui risoluzione è responsabilità di particolari macchine chiamate name server. In realtà il name server è un programma software che può girare in qualunque macchina connessa alla rete, e che mantiene l'associazione tra nomi e indirizzi IP, fornendo tali corrispondenze quando richiesto da un altro programma chiamato name resolver. Di fatto, si preferisce far girare il name server su una macchina dedicata, che prende anch'essa, a questo punto, il nome di name server. Potete pensare al name server come a una agenda telefonica elettronica, che contiene una lista parziale di nomi e numeri telefonici. In internet infatti, non esiste un singolo elenco telefonico, ma tanti name server che cooperano per fornire quello che è un vero e proprio elenco distribuito. In realtà il sistema funziona in modo gerarchico, un po' come se una certa agenda contenesse solo i prefissi internazionali e il puntatore alle agende di ogni singolo stato, le quali a loro volta contengono i prefissi regionali e i puntatori agli elenchi regionali, e così via, fino ad arrivare all'agenda che contiene solo le estensioni telefoniche di un singolo edificio.

 

IL PROTOCOLLO TCP/IP - 3° PARTE

Innanzi tutto una internet è un sistema di interconnessione fra reti differenti che utilizza sia sistemi dedicati per la connessione, detti gateway, sia uno strato (layer) di protocolli che mostrano alle applicazioni una visione omogenea di una rete virtuale e che sono basati sulla trasmissione di piccoli pacchetti di dati. Ogni pacchetto porta con sé l'indirizzo del destinatario il quale identifica univocamente sia la rete di destinazione che la connessione alla quale deve essere recapitato il pacchetto. Un sistema connesso a più reti della stessa internet avrà quindi più indirizzi IP. Un opportuno software, spesso installato su macchine dedicate, permette di associare a ogni indirizzo un nome di più facile utilizzo da parte degli utenti del sistema. Il formato di questo nome si basa su un insieme di regole dette DNS. Quella che è universalmente conosciuta come Internet è di fatto la principale rete interconnessa esistente, che si estende praticamente su tutto il pianeta.

Data questa premessa, vediamo di approfondire la trattazione dei protocolli TCP/IP. Innanzi tutto qualunque trasferimento di dati implica la trasmissione di bit da un sistema a un altro. Tali dati devono essere correttamente interpretati dai vari sistemi connessi alla rete. Data l'enorme varietà di hardware e di sistemi operativi questo è tutt'altro che banale. Nei protocolli di trasmissione i bit vengono convenzionalmente raggruppati per multipli di otto, detti ottetti. Una volta questo corrispondeva al bus da 8 bit, cioè un byte, tipico dei computer. Oggi la maggior parte dei computer usa parole di almeno 32 bit. Tuttavia non tutte le macchine memorizzano tali parole nello stesso modo. Esistono vari modi per memorizzare un intero rappresentato da 32 bit. In quello detto Little Endian, la posizione più bassa in memoria contiene il byte di ordine più basso dell'intero. Nei sistemi Big Endian avviene esattamente il contrario, cioè la posizione più bassa in memoria contiene il byte di ordine più elevato. In altri sistemi ancora il raggruppamento viene fatto con parole da 16 bit, in cui la parola meno significativa viene appunto prima. Il risultato è lo stesso del Little Endian ma con i byte invertiti all'interno di ogni singola parola. È evidente che non è pensabile che sia la rete a gestire tutti questi modi diversi di interpretare i dati, anche perché di solito i protocolli di trasmissione non entrano nel merito di come ragionano i singoli sistemi, ma si occupano solamente di trasferire in modo più o meno affidabile i dati a loro affidati. Ne consegue la necessità di definire un formato standard valido per tutti i dati che corrono lungo i collegamenti, lasciando a i vari sistemi il compito di effettuare le opportune conversioni locali. Lo standard internet prevede che gli interi vengano trasmessi a partire dal byte più significativo, secondo lo stile del Big Endian.

Così in un pacchetto, un intero ha il byte più significativo verso la testa del pacchetto e quello meno significativo verso la coda dello stesso.

A questo punto i sistemi sono in grado di scambiarsi i dati in modo non equivoco. Ma come fa a sapere la rete internet che un sistema è collegato, e soprattutto, come avviene l'associazione tra l'IP address e l'indirizzo fisico di rete? Ogni rete fisica infatti ha un suo formato per gli indirizzi fisici assegnati alle connessioni di rete. In generale esistono due modi di assegnare indirizzi fisici alle macchine connesse in rete. In una rete piccola, come può essere una Token Ring, cioè un anello di un paio di centinaia di macchine al massimo, a ogni connessione può essere assegnato un intero basso, per esempio compreso tra 1 e 254. Questo sistema ha il vantaggio di associare l'indirizzo fisico alla connessione piuttosto che alla scheda che permette la stessa. Per cui, se la scheda si rompe, l'utente può cambiarla senza dover tuttavia modificare l'indirizzo fisico di rete, purché imposti sulla nuova scheda lo stesso indirizzo di quella vecchia. Lo svantaggio è che non esiste alcun controllo che impedisca a due utenti sulla stessa rete di impostare lo stesso indirizzo fisico, creando così una collisione. In altri tipi di reti, come per esempio Ethernet, ogni scheda ha già preimpostato da parte del costruttore un indirizzo fisico fisso, per cui non c'è alcun rischio di collisione, ma cambiare la scheda vuol dire dover necessariamente cambiare indirizzo fisico. Inoltre, dato che questo indirizzo è unico non solo fra le schede installate su una certa rete, ma in assoluto fra tutte le schede costruite, esso è generalmente molto lungo. Nel caso di Ethernet è di ben 48 bit.

Associare un IP address a un sistema con indirizzi formati da piccoli numeri e per giunta tali che a parità di connessione l'indirizzo non cambia mai, come nel caso di una rete proNET-10, è molto semplice. Per esempio, per un IP address di classe C, si può usare l'indirizzo fisico come host identifier. Così, se la rete ha IP address del tipo 10.214.32.x, l'host con indirizzo fisico 16 avrà IP address 10.214.32.16. Un altro paio di maniche è gestire indirizzi molto più lunghi dei 32 bit utilizzati per gli indirizzi internet, e per giunta che possono cambiare nel tempo a parità di connessione. Ovviamente si potrebbe tenere da qualche parte una tabella per gli accoppiamenti, e di fatto si fa così, ma non è certo molto pratico pensare che qualcuno la tenga aggiornata a mano. Il problema è stato risolto efficacemente utilizzando un meccanismo di risoluzione dinamica implementato dal protocollo ARP, o Address Resolution Protocol.

ARP funziona più o meno così. Quando un host deve spedire un pacchetto a un certo destinatario, spedisce a tutti gli host nella stessa rete fisica un messaggio in cui chiede chi è l'host con quel ben preciso IP address. Nello stesso messaggio mette anche i propri indirizzi, sia quello fisico che quello IP. Si adopera cioè una tecnica di broadcasting. L'host il cui IP è quello cercato, rimanda indietro al richiedente il proprio indirizzo fisico, permettendo così l'associazione tra i due. Ciò è possibile in quanto esso ha comunque ricevuto anche l'indirizzo fisico del mittente. Ma allora per ogni pacchetto che va spedito a un certo IP address è necessario prima mandare un pacchetto a tutti gli host nella rete? E perché allora non mandare direttamente il pacchetto da trasmettere a tutti, invece di chiedere prima chi è che ha un certo indirizzo IP? Ovviamente la cosa non funziona così, anche perché si rischierebbe di appesantire inutilmente la rete con pacchetti che vengono recapitati ai sistemi sbagliati. Quello che si fa è di mantenere presso ogni host una tabella con tutti gli accoppiamenti già trovati, e di aggiornarla periodicamente per evitare che diventi obsoleta. A questo punto i meccanismi di broadcasting servono ad aggiornare tali tabelle. Per esempio, se un host deve spedire un pacchetto a un certo indirizzo IP, prima controlla nella sua tabella se non ha già l'indirizzo fisico del destinatario. Solo nel caso l'informazioni manchi, l'host spedisce a tutti gli altri host il messaggio di richiesta. Quando questo arriva a un qualunque host, sia esso il vero destinatario o no, ogni host aggiorna la sua tabella con l'indirizzo fisico e quello IP del mittente, tanto per guadagnare tempo. Il destinatario, in più, spedisce indietro anche il suo indirizzo fisico al mittente, così da potergli permettere di aggiornare la sua tabella di indirizzi. Un'ulteriore tecnica che si usa per assicurarsi che tali tabelle siano sempre aggiornate, è quella di far distribuire la propria

coppia di indirizzi, fisico ed IP, ogni qual volta un sistema si connette alla rete, per esempio al reboot.

ARP non viene considerato propriamente un protocollo internet, quanto un meccanismo della rete fisica. Su ARP si basa il protocollo IP per far comunicare fra loro le varie macchine quando non è possibile risolvere in altro modo gli indirizzi IP in indirizzi fisici. Un protocollo analogo è il RARP, o Reverse Address Resolution Protocol, con il quale una macchina senza disco fisso (diskless) è in grado di conoscere il proprio indirizzo IP a partire da quello fisico. Per far ciò la rete deve avere uno o più RARP Server, i quali contengono una tabella di associazione fra gli indirizzi IP e quelli fisici di tutte le macchine diskless. Anche questo protocollo si basa su un messaggio mandato in broadcasting. L'esistenza di questo protocollo è legata al fatto che una macchina diskless non può memorizzare il proprio indirizzo IP in alcun posto, non avendo memoria secondaria.

E veniamo ora al TCP/IP vero e proprio. Come detto prima l'architettura internet è basata su tre livelli. L'Application Services è il livello più alto, cioè quello delle applicazioni. I programmi che utilizzate quando usate internet ricadono in questo livello. Il Reliable Stream Transport Service è il livello intermedio. Esso si occupa dell'affidabilità della comunicazione, gestendo gli errori di trasmissione e la perdita di eventuali dati. Esso inoltre fornisce una visione della comunicazione ad alto livello, in cui esiste una connessione tra i due host che si trasmettono grandi volumi di dati. Il livello più basso, chiamato Connectionless Packet Delivery Service è quello che effettua la spedizione vera e propria dei singoli pacchetti, senza garantire l'affidabilità sulla singola trasmissione, nella modalità detta connectionless.

Il protocollo su cui si basa il livello più basso della torre internet è appunto l'Internet Protocol, o IP. Tale protocollo si basa su alcuni concetti fondamentali. Innanzi tutto il servizio che fornisce è detto unreliable, cioè inaffidabile, in quanto non dà alcun garanzia che il singolo pacchetto arrivi effettivamente a destinazione. In secondo luogo è detto connectionless, cioè senza connessione diretta, in quanto la trasmissione non avviene direttamente verso il destinatario, ma il messaggio è lanciato nella rete lasciando poi a questa il compito di portarlo a destinazione utilizzando l'indirizzo IP dell'host destinatario. Infine si parla di best-effort delivery, cioè spedizione al meglio delle possibilità, in quanto la rete fa tutto il possibile per portare comunque a destinazione il pacchetto. In pratica l'IP si comporta come un naufrago su un'isola deserta che lancia nella corrente un messaggio in una bottiglia per un tizio che si trova su di un'altra isola dello stesso arcipelago, contando sul fatto che se la bottiglia arriva sull'isola sbagliata qualcuno ributterà a mare il messaggio fintanto che non arriverà a destinazione. Detta così c'è quasi da stupirsi che internet funzioni così bene. Anzi, che funzioni del tutto! In realtà non dimentichiamoci che sopra al livello più basso ce n'è un altro che garantisce appunto l'affidabilità della comunicazione. Torniamo comunque all'IP. Esso è formato da tre regole base: come è fatto il pacchetto da trasmettere, detto IP datagram, come avviene la scelta del cammino che il pacchetto segue per raggiungere il destinatario, come gli host e i gateway devono trattare i pacchetti e in particolare le modalità per l'emissione dei messaggi di errore e quelle per la soppressione dei pacchetti

IL PROTOCOLLO TCP/IP - 6° PARTE

Se l’IP rappresenta il braccio del TCP/IP, il TCP ne rappresenta la mente. Il primo si limita a spedire rapidamente i dati che gli arrivano senza preoccuparsi troppo se qualcosa va male. Il secondo si occupa invece di controllare che l’informazione passatagli dai livelli superiori arrivi correttamente a destinazione. Insieme sono sicuramente una coppia molto affiatata.

In questo articolo useremo il termine applicazioni per indicare tanto i protocolli applicativi come FTP o SMTP, quanto i programmi applicativi veri e propri, salvo indicazione contraria. Indicheremo inoltre con il termine utente di un servizio colui che utilizza tale servizio, sia esso direttamente una persona, un’applicazione, o un protocollo. Per esempio, il TCP è un utente dell’IP.

C’è subito da dire due cose importanti sul TCP. La prima è che lo standard del TCP non definisce né l’implementazione dello stesso, né le modalità con cui un’applicazione accede a i servizi di questo protocollo. Esso definisce solamente le caratteristiche di tali servizi, per cui si possono trovare molte differenti implementazioni del TCP, ognuna con la propria interfaccia applicativa. Per chi non programma ricordo che un’interfaccia applicativa o API (Application Programming Interface) non è altro che l’insieme delle funzioni, delle istruzioni, dei parametri e dei blocchi di controllo che vengono utilizzati dai programmatori per accedere ai servizi di un sistema. Per esempio, se ho un sistema di posta elettronica potrei definire un’API basata su due funzioni, una chiamata spedisci, e una chiamata ricevi . Per ogni funzione sarebbero poi da definire quali informazioni sono da passare al momento dell’utilizzo (parametri in ingresso), quali si ottengono una volta espletato il servizio (parametri di ritorno), eventuali codici di errore, e le regole di utilizzo delle singole funzioni. Il motivo che sta alla base della scelta di non standardizzare l’interfaccia con il TCP è che in molti casi questo protocollo è direttamente definito nel sistema operativo, o comunque fa parte del cosiddetto corredo di base di un sistema, per cui si è voluto evitare di forzare una sintassi che potesse essere in contrasto con quella nativa del sistema ospite. Il secondo punto fondamentale è che il TCP è stato definito per funzionare su un qualsiasi sistema di trasmissione dati a pacchetto, e non necessariamente solo sull’IP. Di fatto esso può essere poggiato, per esempio, direttamente sopra una rete Ethernet senza bisogno di un livello Internet intermedio.

Ma qual è lo scopo del TCP nell’architettura internet? Il protocollo non fornisce le garanzie di affidabilità e robustezza necessarie per implementare un sistema di trasmissione dati sicuro e di facile gestione. L’IP è inaffidabile e benché schermi lo sviluppatore dalla conoscenza della rete fisica, fornisce ancora una visione di livello troppo basso del sistema di reti interconnesse. Questo vuol dire che l’IP è troppo complesso per essere utilizzato direttamente dalle applicazioni. Per avere un protocollo di trasmissione affidabile abbiamo bisogno di gestire tutte le possibili situazioni di errore, la duplicazione o la perdita dei pacchetti, la caduta delle connessioni o di un router, e via dicendo. Se le

applicazioni utilizzassero direttamente i servizi dell’IP, ognuna di esse dovrebbe implementare una serie alquanto complessa di algoritmi e servizi per tenere conto di tutto ciò. A parte il fatto che esistono relativamente pochi programmatori in grado di far questo fra gli svariati milioni di sviluppatori di applicazioni, nella maggior parte dei casi si tratterebbe di reinventare ogni volta la ruota. In generale questi problemi, seppure complessi, sono abbastanza standard, per cui si è pensato di poggiare sui sistemi di trasmissione a pacchetti un protocollo affidabile che potesse essere implementano da sviluppatori altamente specializzati, lasciando così agli altri la possibilità di concentrarsi sulla logica applicativa piuttosto che sugli aspetti specifici della trasmissione dei dati a basso livello.

Vediamo allora quali sono le caratteristiche principali del TCP, eventualmente comparate a quelle dell’IP.

Innanzi tutto il TCP fornisce una visione dei dati di tipo a flusso (data stream), cioè i dati sono ricevuti in sequenza e nello stesso ordine con il quale sono stati trasmessi. A questo livello cioè, l’utente del TCP spedisce i dati come un singolo flusso di byte e nello stesso modo li riceve. Nell’IP avevamo invece la divisione dei dati in pacchetti che potevano subire un’ulteriore frammentazione se si trovavano a passare attraverso reti caratterizzate da una soglia molto bassa sulle dimensioni dei frame fisici. I pacchetti potevano inoltre arrivare in ordine sparso rispetto a quello di trasmissione.

Secondo punto: nell’IP non si sa mai a priori il cammino che effettua un pacchetto. Il TCP fornisce al suo utente una visione del collegamento come se esso fosse una linea dedicata. Ovviamente sotto sotto il meccanismo è ancora quello a pacchetti, ma la cosa è schermata agli utilizzatori del TCP. Tale caratteristica è detta vitual circuit connection, cioè circuito di connessione virtuale. Il TCP si basi sul concetto di connessione, piuttosto che su quello di indirizzo come fa invece l’IP. Una connessione, per definizione, richiede la definizione di due punti piuttosto che di uno solo, detti punti terminali o estremi della connessione (endpoint). Parleremo anche di interlocutori per indicare gli utenti posti agli estremi della connessione.

Terzo punto: abbiamo visto che l’IP divide i dati in pacchetti che vengono costruiti sulla base di esigenze di trasmissione legate alle varie reti fisiche su cui si poggia il sistema. D’altra parte le applicazioni dividono i dati in funzione delle esigenze applicative. Per esempio, un’applicazione di posta elettronica può considerare una lettera da 8.000 caratteri una singola unità dati, mentre un protocollo per la gestione della rete può avere l’esigenza di spedire tanti piccoli messaggi di non più di 16 byte l’uno. Il TCP permette di disaccoppiare il modo di dividere i dati delle applicazioni da quello dell’IP. Così la lettera di cui sopra viene prima spezzata in tante parti, spedita via IP e poi ricomposta dal livello TCP del destinatario, mentre per i messaggi di controllo avviene il contrario: prima vengono accumulati in un singolo pacchetto, e poi rispezzettati presso il destinatario. Questo meccanismo è detto buffered transfer. Naturalmente può sorgere l’esigenza di forzare la trasmissione dei dati anche se il buffer non è pieno. Per esempio, se serve sapere se un certo sistema è attivo o meno manderò prima un messaggio di interrogazione, e solo una volta ricevuta la conferma incomincerò a spedire gli altri dati. Dato che il messaggio di interrogazione è più piccolo del buffer, esso non verrebbe realmente spedito dal TCP fintanto che questi non è stato riempito. È quindi necessario forzare la trasmissione del primo messaggio (push) se si vuole evitare di attendere inutilmente la risposta a un messaggio che in realtà non è mai partito.

Quarto punto: per quanto intelligente, il TCP si preoccupa di trasferire i dati che gli vengono passati senza entrare in merito a il loro significato dal punto di vista applicativo. In che modo il flusso di dati vada interpretato semanticamente è responsabilità delle due applicazioni che utilizzano la connessione TCP per cooperare. Questo vuol dire che se un’applicazione manda alla sua controparte una serie di indirizzi, questi arriveranno uno di seguito all’altro nel giusto ordine, ma senza alcuna garanzia che ogni buffer contenga un numero intero di indirizzi. Sta all’applicazione ricomporre un indirizzo capitato a cavallo di due buffer consecutivi. Si parla quindi di flusso senza struttura (Unstructured Stream).

Quinto e ultimo punto: le connessioni TCP permettono il trasferimento contemporaneo dei dati in entrambe le direzioni, quello che nel gergo delle comunicazioni si chiama una connessione full-duplex. Si hanno cioè due flussi che scorrono indipendentemente in direzioni opposte, senza interagire fra loro. Le applicazioni hanno comunque la possibilità di passare alla modalità half duplex semplicemente bloccando uno dei due flussi di dati.

Ma in che modo il TCP garantisce quella affidabilità che manca all’IP? Il meccanismo di base utilizzato sia dal TCP che da molti altri protocolli cosiddetti "affidabili" è quello della ritrasmissione in caso di mancata conferma (positive acknowledgement with retrasmission). Si tratta di un meccanismo concettualmente semplice: ogni qual volta uno dei due interlocutori di una connessione spedisce dei dati, questi attende una conferma dell’avvenuta ricezione. Se questa arriva entro un tempo stabilito viene spedito il pacchetto successivo, altrimenti l’applicazione rispedisce quello precedente. Tale tempo viene misurato con un timer che viene fatto partire ogni volta che un pacchetto è spedito. Questo meccanismo risolve il problema dei pacchetti persi o danneggiati, ma può crearne un altro. Supponiamo che a causa di problemi di saturazione della rete un pacchetto ci metta molto più tempo del previsto ad arrivare. A questo punto il mittente, non vedendosi arrivare indietro la conferma ne rispedisce una copia. Succede così che il destinatario riceve a una certa distanza l’uno dall’altro due copie dello stesso pacchetto. Il problema della duplicazione dei pacchetti viene risolto facendo numerare sequenzialmente al mittente tutti i pacchetti da spedire e facendo verificare al destinatario la sequenza ricevuta. Naturalmente questo non vale solo per i messaggi ma anche per le conferme agli stessi. Infatti anche una conferma potrebbe venire erroneamente duplicata. Per evitare questo ogni conferma riporta il numero di sequenza del messaggio a cui si riferisce, permettendo così al mittente di verificare che a ogni messaggio spedito corrisponda una e solo una conferma di ricezione. È un po' lo stesso meccanismo di una raccomandata con ricevuta di ritorno.

In realtà gli algoritmi utilizzati dal TCP sono un po' più complicati, e tengono conto di tutta una serie di situazioni che si possono verificare. Senza contare che il tempo di attesa prima della ritrasmissione è un punto chiave di tutto il discorso. Se si attende troppo poco si rischia di generare un sacco di duplicati inutili, saturando per giunta la rete, mentre se si attende troppo si rischia di abbassare notevolmente e inutilmente le prestazioni della trasmissione dei dati, rallentando le applicazioni alle estremità della connessione.

Il meccanismo della conferma di ricezione con ritrasmissione ha inoltre un grosso svantaggio. Anche se i tempi di attesa sono scelti in modo ottimale, esso causa un notevole sottoutilizzo della rete. Infatti, indipendentemente dalla capacità della rete, i due interlocutori passano la maggior parte del tempo attendendo le varie conferme. È un po' come avere un tubo nel quale vengono fatte cadere una a una delle palline numerate in sequenza. All’altra estremità del tubo c’è una cesta poggiata su un prato, un po' distante dal foro di uscita. Se la pallina cade nella cesta fa rumore, altrimenti cade nel prato e non si sente niente. Se ogni volta che metto una pallina nel tubo aspetto di sentire il rumore che mi conferma che la pallina è caduta nel cesto, il tubo resta per la maggior parte del tempo vuoto. Una tecnica di ottimizzazione usata dal TCP per rendere più efficiente il meccanismo appena descritto è quella delle finestre di scorrimento (sliding window). Funziona più o meno in questo modo. Immaginate di immettere nel tubo una sequenza di dieci palline senza attendere che la prima sia arrivata. Come si sente il primo flop si aggiunge un’undicesima pallina, e poi una dodicesima e così via. Se si salta un flop si reinserisce una pallina con lo stesso numero di quella che non è arrivata, tanto il destinatario può comunque riordinare le palline utilizzando i numeri scritti sopra. Il numero di palline che compongono il trenino da spedire indipendentemente dalla ricezione del flop si chiama dimensione della finestra di scorrimento (sliding window size). Se si sceglie una dimensione tale da riempire tutto il tubo nella sua lunghezza si sfrutta al massimo la capacità dello stesso.

In pratica questo sistema divide la sequenza di pacchetti in tre fasce. La prima è rappresentata dai pacchetti spediti e di cui si è avuta la conferma di ricezione. La seconda è formata dai pacchetti spediti ma dei quali non si sa ancora niente, e la terza è formata dai pacchetti ancora da spedire. Con questa tecnica il TCP mantiene un timer per ogni singolo pacchetto che appartiene alla seconda fascia. Il nome "Finestra di scorrimento" deriva dal fatto che è come se ci fosse una finestra ampia quanto il trenino di pacchetti che possono essere spediti senza attendere la conferma dell’avvenuta ricezione che scorre in avanti un pacchetto alla volta ogni qual volta arriva una conferma. Anche in questo caso, come in quello del tempo di attesa prima di ritrasmettere un pacchetto, le dimensioni della finestra di scorrimento rappresentano un fattore critico per determinare l’efficenza del sistema. In generale, se le dimensioni della finestra sono maggiori del tempo di attesa per il singolo pacchetto, allora la finestra continua a scorrere regolarmente senza interruzioni, salvo nel caso di ritrasmissioni, e la capacità di carico della rete viene sfruttata al massimo.

 

IL PROTOCOLLO TCP/IP - 7° PARTE

Affinché infatti due applicazioni possano comunicare fra di loro esse debbono conoscersi e il sistema di trasmissione che le serve deve sapere a chi effettivamente vanno recapitati i dati. È evidente che non basta l'indirizzo IP, che identifica univocamente un host nella rete. Basti pensare che un PC collegato in rete ha in genere un solo indirizzo IP, a meno che non sia collegato a più reti fisiche, come per esempio un gateway. Se una lettera viene spedita via rete a un certo indirizzo come fa TCP a sapere a quale applicazione deve far arrivare i dati? Un sistema potrebbe essere quello di assegnare un identificativo a ogni singola applicazione, ma come garantire allora l'univocità dell'identificativo? Senza contare che questo costringerebbe la controparte a sapere a priori tale valore per ogni possibile destinatario. Non è inoltre detto che un utente utilizzi sempre lo stesso programma per spedire o ricevere la posta elettronica. In realtà, più che la specifica applicazione, quello che è importante identificare è la funzione, come per esempio trasferire file oppure spedire posta elettronica.

La soluzione è quella di definire dei punti di ingresso e di uscita virtuali chiamati porte. Ogni porta rappresenta di fatto un punto di accesso a un'applicazione nel sistema. Si tratta in pratica di un'estensione del concetto di porta hardware. Un PC moderno, per esempio, può avere porte hardware parallele, seriali, video, audio e di vari altri tipi. Ad ogni porta possono essere attaccati dispositivi molto differenti. Per esempio, a una porta parallela è possibile attaccare una stampante, uno scanner, un'unità Cd-Rom oppure un'unità disco ad alta capacità. Tutti questi dispositivi non hanno bisogno di una porta specifica, ma possono utilizzare la stessa porta perché gestiscono flussi di dati simili, possono cioè usare lo stesso protocollo di base per la trasmissione dei dati. 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. D'altra parte anche 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, reperibile a ftp://ds.internic.net/rfc/rfc1060.txt 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 sopra. 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, e 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. Per esempio, supponiamo di implementare via TCP/IP un terminale remoto. Questo vuol dire 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. Non solo: 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.

 

Home Page

 Fibra Ottica

Dispositivi di interconnessione

Wirless

Pila ISO/OSI

Tipi di Topologie

Reti Informatiche