Articolo pubblicato sul n. 89 di MCmicrocomputer (Edizioni Technimedia Srl - Roma) nell'ottobre1989

MCmicrocomputer


Amighevole:
ADPnetwork: una rete per Amiga

di Andrea de Prisco

Come anticipato lo scorso mese, a partire da questo numero presenteremo ADPnetwork, la nostra rete software per Amiga 500, 1000 e 2000 scritta interamente utilizzando l'ADPmttb 2.0, visto, anche quello, sul numero scorso.Copertina del numero di MCmicrocomputer contenente l'articolo

Trattandosi di una realizzazione tutt'altro che banale, sia sotto il profilo teorico che implementativo, la presentazione del lavoro ci terra' impegnati per diverse puntate. Nella versione in cui vedra' la luce su queste pagine, tutti i collegamenti tra le macchine sfruttano l'interfaccia seriale dei singoli sistemi: in questa configurazione, ovviamente, non andremo oltre gli aspetti puramente didattici della realizzazione a causa della bassa velocita' di trasferimento che pero' potra' essere piu' che sufficiente per carichi leggeri. ADPnetwork e' di fatto una piattaforma sulla quale costruire applicazioni distribuite, file system distribuiti, sistemi fault tollerant ed e' indipendente, questo e' molto importante, dalla natura del mezzo di comunicazione fisico adottato. Per essere ancora piu' precisi, il software di rete di ADPnetwork e' addirittura indipedente anche dalla macchina, l'Amiga, sulla quale attualmente gira: basta infatti riscrivere l'mttb per un altro sistema multitasking (ad esempio Unix, OS/2), aggiungere o togliere un po' di include machine-dependent, ricompilare il tutto e il gioco e' fatto.

Dopo la presentazione del vero e proprio software di rete (tutti i processi che costituiscono ADPnetwork), lascieremo la parola a Marco Ciuchini e Andrea Suatoni che hanno sviluppato un Handler e un NetServer (ovviamente "rigorosamente Amiga") per la rete, in modo da rendere visibile da ogni applicazione in esecuzione su qualsiasi macchina tutte le unita' di ingresso uscita disponibili sull'intera rete. Ciliegina finale, sempre grazie all'handler, la possibilita' di utilizzare la rete anche da WorkBench dove troveremo la nostra brava icona NET (vicino alle altre icone relative a  floppy, harddisk, ram, rad) che una volta click-ata ci mostrera' le icone delle macchine attualmente in rete e click-ando su queste accederemo ai vari device disponibili sui nodi e, conseguentemente, ai file.

Tutto tramite mouse... non male, vero ?

 

Un po' di storia

 

Lo schema di funzionamento "circolare" di ADPnetwork, come vedremo meglio in seguito, e' tutt'altro che originale. Disponendo infatti su ogni macchina di una sola interfaccia di ingresso e una di uscita (nel nostro caso l'I/O seriale) tale forma di comunicazione e' l'unica possibile volendo collegare piu' macchine tra di loro. Altre possibili tipologie (figura 1) sono quelle "a stella", in cui tutte le macchine sono collegate ad un unico nodo centrale, ad "interconnessione completa" in cui ogni macchina e' direttamente collegata con tutte le altre macchine, ad "albero" dove i nodi sono collegati (e accessibili) gerarchicamente come i file di un file system, appunto, gerarchico. Non mancano tipologie piu' complesse, come il "mesh quadrato", "l'ipercube" o le strutture ad "Omega" o, ancor di piu', tipologie miste in cui troviamo varie sottoreti con architetture diverse interconnesse a loro volta tra loro secondo le piu' svariate tipologie.

ADPnetwork, come detto, adotta uno schema di funzionamento "circolare" in cui ogni macchina ha un nodo precedente, dal quale riceve il flusso dei dati, e uno successivo al quale trasmette, o ritrasmette, dati. E' chiaro a questo punto che ogni macchina analizzera' i dati ricevuti dalla rete e dovra' essere in grado di riconoscere messaggi per se' da inoltrare agli opportuni server, oppure da rimettere in circolo non riconoscendosi come destinatario. In questo modo e' sia possibile che qualsiasi macchina dialoghi con qualsiasi altra macchina della rete, sia che in ogni istante (nel senso fisico e non solo in quello logico del termine) piu' macchine effettuino operazioni sulla rete. Quest'ultima caratteristica (non presente nemmeno in architetture ultra diffuse come Ethernet e Token Ring) e' forse la piu' importante di tutta l'architettura di ADPnetwork, ed e' implementata grazie al fatto che la struttura di comunicazione utilizzata e' solo apparentemente condivisa da tutte le macchine. Infatti non succede che l'intero mezzo fisico appartiene a tutti i nodi (con la necessita' quindi di arbitrare l'accesso in maniera centralizzata o distribuita, deterministicamente o non) ma ogni nodo e' proprietario del collegamento alla macchina successiva, e quindi non deve dar conto alla rimanente rete delle sue operazioni. Un'occhiata allo schema di collegamento di figura 2 molto probabilmente vi chiarira' le idee piu' di mille parole.

L'attuale release funzionante di ADPnetwork, la 3.0, permette a qualsiasi processo in esecuzione su qualunque macchina di inviare messaggi a qualsiasi altro processo in esecuzione su qualsivoglia altra macchina collegata alla rete. Ogni messaggio puo' essere di lunghezza arbitraria e per inoltrarlo via rete il processo mittente dovra' naturalmente specificare il nodo destinatario, la porta mttb esistente su quel nodo (creata cioe' dal processo destinatario) e consegnare il messaggio al software di rete. Sara' poi questo che, impacchettandolo opportunamente ed utilizzando l'interfaccia d'uscita verso la macchina "successiva" fara' in modo (naturalmente con la complicita' di tutti i processi di rete di tutte le macchine "attraversate") che il messaggio giunga a destinazione e sulla giusta porta.

Attualmente ADPnetwork prevede anche alcune forme di tolleranza ai guasti, ivi comprese cadute del supporto fisico o piu' semplicemente spurie di trasmissione che potrebbero cambiare il contenuto di un msg. Per caduta del supporto fisico intendiamo anche (a dire il vero "soprattutto") accidentali sconnessioni delle macchine nel bel mezzo di una operazione sulla rete. L'abbiamo visto coi nostri occhi (e vi assicuriamo che la cosa e' affascinante) provocando artificialmente una sconnessione mentre una macchina stava stampando su video (a seguito di un TYPE NET:ecc.ecc.) un file remoto. Non essendo possibile la comunicazione (i connettori erano stati brutalmente staccati) la visualizzazione si e' arrestata per riprendere esattamente dallo stesso punto, e senza battere ciglio, pochi attimi dopo aver ripristinato il collegamento. Come vedremo piu' approfonditamente in seguito, tale meccanismo e' implementato attraverso due appositi processi mttb di ADPnetwork (Timer e Replay) che ritrasmettono automaticamente le porzioni di messaggio che non risultano essere arrivate a destinazione.

 

Schema circolare

 

Come detto prima, ADPnetwork e' indipendente dal mezzo fisico adottato per mettere in comunicazione piu' macchine. L'unica cosa necessaria, e' il collegamento "circolare" in cui l'interfaccia out della macchina 'j' e' collegata all'interfaccia di ingresso della macchina '(j+1) mod n' dove 'n' e' il numero delle macchine in rete. Nel caso minimale di due macchine in rete, bastera' un collegamento dalla macchina A alla macchina B e, viceversa, uno da B ad A. Se le macchine sono tre avremo un cavo da A a B, uno da B a C e uno da C ad A. E cosi' via per collegamenti di piu' macchine. Un'altra caratteristica particolare di ADPnetwork e' che non e' necessario informare i singoli nodi dei nomi degli altri nodi esistenti in quanto ogni accesso a macchine remote viene di volta in volta "tentato" confidando sull'effettiva esistenza dello stesso. Cio' significa, ad esempio, che tanto l'ingresso in rete, quanto l'uscita dalla stessa, non e' subordinato ad operazioni di servizio atte ad informare le altre macchine del cambiamento. L'unica cosa, banalmente, necessaria, e' il fatto che ogni macchina per fare parte della rete deve essere:

 

(1) fisicamente collegata alla struttura.

(2) abbia in esecuzione i processi di gestione per la rete.

(3) abbia un nome unico formato da caratteri alfabetici.

 

Il nome della macchina e' passato ai processi del software di rete in esecuzione sul nodo e serve sia per ricevere messaggi che per trasmetterli. Infatti e' necessario che qualsiasi messaggio in viaggio sulla rete sia sempre accompagnato da un nome del mittente, un nome del destinatario piu' altre informazioni di servizio che avremo modo di analizzare meglio in seguito.

Poniamoci ora dal punto di vista di un singolo nodo e cerchiamo di spiegare a porole e nel modo piu' comprensibile possibile (si spera) il funzionameno a grandi linee di ADPnetwork. Diciamo, per semplicita', che il nodo in questione sia "Platone" e che sulla rete esistano altri due nodi instanziati come "Socrate" e "Pitagora". Il collegamento circolare e' mostrato in figura 3.

Sull'interfaccia di ingresso di Platone arriva ad un certo punto un messaggio di Socrate per Pitagora. Platone non lo riconosce come proprio e non fa altro che reinviare il messaggio senza alcuna modifica sul suo canale d'uscita verso la macchina successiva (che in questo caso e' Pitagora, ma poteva pure non esserlo). In questo primo esempio, i processi di Platone hanno permesso la comunicazione tra due nodi non direttamente connessi. Da notare, anche se sicuramente non ce n'e' bisogno, che i processi di gestione della rete girano in background su tutte le macchine e quindi un eventuale operatore sulla macchina Platone che sta ad esempio scrivendo una lettera o divertendosi col DeLuxe Paint non e' si accorge minimamente del fatto che in quel momento la sua macchina sta "servendo" la rete. Questo almeno in teoria, infatti, utilizzando la seriale come interfaccia pret-a-porter su tutte le macchine, un lieve rallentamento delle operazioni si avvertira' comunque. Ma come detto prima la scelta della seriale e' solo di comodo e nulla vieta di realizzare delle schede elettroniche aggiuntive in modo da demandare il riconoscimento dei messaggi e relativa eco sulla rete ad hardware apposito ed esterno all'architettura Amiga.

Tornando allo schema-esempio di figura 3, grazie all'intercessione di Platone, Pitagora riceve il messaggio inviato da Socrate. Diciamo che a questo punto, Pitagora decide di rispondere al messaggio preparando una risposta, appunto, per Socrate. Quello che fa e' scaricare tale messaggio sull'interfaccia di uscita che questa volta e' direttamente connessa all'interfaccia d'ingresso di Socrate, dunque giunge immediatamente a destinazione. E' importante sottolineare che in tutti i casi, ogni macchina oltre a non sapere a priori i nomi delle macchine collegate, tantomeno conosce l'ordine della disposizione. Quindi l'attuale situazione di Pitagora che invia a Socrate e' esattamente la stessa della precedente in cui Socrate spediva a Pitagora: l'unica cosa che una macchina mittente puo' fare e' inoltrare il messaggio sulla sua interfaccia d'uscita sperando che la macchina destinataria esiste.

Tutti i lettori a questo punto si chiederanno cosa succede se realmente una macchina invia un messaggio ad un macchina inesistente, vuoi per un errore di digitazione ("Pitagola" in luogo di "Pitagora") vuoi perche' il destinatario finora vivo e vegeto ha deciso, per cause a noi ignote, GURU compresi!, di uscire dalla rete. La risposta e' quantomai banale: infatti come detto prima ogni messaggio circolante sulla rete e' sempre accompagnato da un nome del mittente e un nome del destinatario, quindi un messaggio diretto ad un destinatario inesistente sara' semplicemente scartato da tutti i nodi e giungera' nuovamente al mittente. Quindi ogni macchina, prima di re-inoltrare sulla rete un messaggio, oltre a controllare che il destinatario sia diverso dal nome proprio, deve controllare anche che il mittente non sia se' stesso: se cio', di contro, si verifica, vorra' dire che il messaggio ha fatto tutto il giro dell'architettura circolare con conseguente deduzione dell'inesistenza del destinatario in oggetto.

 

Struttura dei Pacchetti

 

Introduciamo a questo punto i cosiddetti pacchetti di rete, veri e propri veicoli di informazione trasmessa, che d'ora in poi chiameremo frame per non confonderli con i (gia' esistenti) pacchetti DOS o DOS packet che di si voglia.

Infatti la spedizione di un messaggio da una macchina ad un'altra non avviene "sparando" direttamente l'oggetto della trasmissione sul canale d'uscita, ma avviene tramite una codifica in frame che grazie appunto alla frammentazione permette di minimizzare i fallimenti di trasferimento. Se spedissimo interi file sulla rete cosi' come sono, in caso d'errore di trasmissione occorrerebbe rispedire nuovemente l'intero file, mentre frammentando la spedizione, bastera' re-inoltrare solo i frame giunti non correttamente a destinazione. Naturalmente la frammentazione implica anche un aumento di informazione trasmessa, resa necessaria al destinatario per ricomporre il messaggio originario man mano che arrivano i frame.

In figura 4 e' mostrato lo schema di un frame di rete. Cominciamo col dire che questi hanno lunghezza variabile tra 128 e 5120 byte. Cio' significa che messaggi lunghi meno di 5 K viaggeranno su un solo frame (di lunghezza appunto variabile) mentre per messaggi piu' lunghi si operera' la frammentazione. In questo caso se 'n' sono i frame necessari per la spedizione, i primi 'n-1' saranno lunghi 5 K, mentre l'ultimo avra' nuovamente lunghezza variabile a seconda di quanti byte rimangono da spedire. Facciamo un esempio: bisogna spedire un messaggio lungo 13 k da una macchina ad un'altra. Sono necessari tre frame, i primi due da 5 K l'uno, il terzo da 3 K. Semplice, no?

Vediamo ora in dettaglio quali informazioni sono contenute in ogni singolo frame di rete. Il primo campo, di un byte, contiene appunto la lunghezza del frame espresso in multipli di 128 byte. In questo campo ci sara' dunque un numero compreso tra 1 e 40 ( 40x128=5120 ). Seguono 10 byte per il nome del destinatario del frame e 10 per il mittente, necessari, come detto, sia per recapitare i frame che per "dedurre" che il destinatario non esiste. Le rimanenti informazioni sono di servizio ovvero sono necessarie al software di rete per controllare la trasmissione e la ricomposizione del messaggio originario. Il primo di questi campi indica il tipo del messaggio: come vedremo meglio in seguito messaggi di tipo diverso potranno circolare sulla nostra rete e saranno trattati in maniera diversa. Segue un byte per un primo check sum sui primi 22 byte del frame: questo campo e' utilizzato per  risincronizzarsi su un frame valido qualora si "perdesse per strada" qualche byte trasmesso. Dopo il byte di check sum troviamo un altro byte, detto chop byte, che indica quanti byte in coda al messaggio sono non significativi: questo di manifesta tutte le volte (ovvero quasi sempre) che il messaggio trasmesso non riempie perfettamente l'untimo frame inviato. Il campo CRC (Cyclical Redundance Code) controlla invece possibili errori di trasmissione sulla vera e propria porzione di messaggio trasmessa. Gli ultimi tre campi servono per ricostruire il messaggio originario man mano che arrivano i frame. I primi due (costanti su ogni frame di uno stesso messaggio) indicano l'effettiva lunghezza del messaggio originario prima della frammentazione e l'identificatore di messaggio che viene incrementato, localmente ad ogni macchina, ogni nuova richiesta di spedizione su rete. L'untimo campo, Offset, indica a partire da quale byte il corpo di questo frame va posizionato: nessuna assunzione e' fatta circa la sequenzialita' dei frame di un messaggio. Infatti frame arrivati male verranno rispediti solo dopo la prima spedizione dell'ultimo frame e quindi e' sempre necessario sapere cio' che arriva a quale porzione del messaggio originario corrisponde.

Per finire, tutti i rimanenti byte del frame contengono la parte di messaggio spedita.

 

Il Software di Rete

 

Per Software di Rete (SDR) intendiamo i processi lanciati in background su ogni macchina atti a permettere la comunicazione tra due qualsiasi nodi. Utilizzando l'SDR e' possibile a due processi qualunque lanciati su due macchine distinte di scambiare agevolmente messaggi. E' su questo SDR che Marco Ciuchini e Andrea Suatoni hanno installato i loro Net-Handler e NetServer per realizzare una sorta file system distribuito permettendo tanto l'utilizzo sotto WB della rete quanto l'accesso a file remoti da shell e da ogni programma commerciale purche' questo sia stato realizzato all'origine secondo canoni di programmazione "puliti". Tanto per non fare nomi, il nostro fiore all'occhiello italiano, C1-Text della Cloanto Italia, caricato su una macchina collegata in rete, nei menu' "Aprire documento" o "Memorizzare documento" mostra un nuovo button "NET" tramite il quale possiamo leggere e salvare file su altre macchine.

L'SDR e' attualmente formato da diversi processi cooperanti (scritti tutti, ovviamente, in ADPmttb 2.0) e per il momento vi mostreremo il funzionamento dei quattro moduli piu' importanti: Packer, Sender, Dispatcher e Spacker. Il loro schema di cooperazione e' mostrato in figura 5.

Poniamoci allora dal punto di vista di una macchina che deve spedire un messaggio ad un processo in esecuzione su un'altra macchina e vediamo cosa succede. L'ipotesi di collegamento e' sempre quella di figura 3, che poi e' quella che ci ha accompagnato in tutti questi mesi di sperimentazione e realizzazione qui in redazione. Allora, diciamo che Socrate vuole spedire un messaggio lungo 23 K a Pitagora. Cio' che deve fare e' mandare un messaggio al processo Packer in esecuzione sulla sua stessa macchina, contenente il nome del destinatario ("Pitagora") il tipo del messaggio (per il momento ignoreremo questo campo) la lunghezza del messaggio, 23552 pari cioe' a 23x1024 byte, e il messaggio vero e proprio cioe' i 23552 byte da spedire. Ricevuto il messaggio, il Packer provvede a spezzare i 23552 byte in 5 porzioni, quattro delle quali lunche circa 5 K e l'ultima circa 3 K. Il circa e' dovuto al fatto che ogni frame e' lungo un multiplo di 128 byte, compreso pero' l'header che contiene le informazioni trattate nel precedente paragrafo. Ogni frame costruito dal Packer e' passato al processo Sender che provvede alla effettiva spedizione sul canale di uscita. Lo stesso Sender riceve sulla medesima porta anche frame provenienti dal Dispatcher che, ricevendoli dal canale di ingresso, ma non riconoscendoli come destinati a quel nodo, li inoltra alla macchina successiva. Questa sara' l'operazione svolta da Platone che, come mostrato in figura 3, si trova tra Socrate e Pitagora. All'interno di quest'ultima, man mano che giungono i frame al suo Dispatcher, riconosciuti come propri, i frame sono inviati al processo Spacker che provvede a "ri-incollare" le 5 porzioni di messaggio arrivate in sequenza. Non appena il processo Spacker si accorge di aver ricomposto interamente il messaggio originario (e se ne accorge sapendo da ogni frame la lunghezza totale e la posizione relativa deii vari pezzi arrivati) provvede a spedirlo al processo opportuno, funzione del "tipo messaggio" che non abbiamo ancora trattato. Comunque per il momento e' tutto. Mentre qui in redazione continuamo a fare gli ultimi ritocchi "ottimizzatori" al SDR il sottoscritto e all'Handler di rete l'accoppiata vincente Ciuchini-Suatoni, vi diamo appuntamento al prossimo numero per un piu' approfondito commento al funzionamento dei processi e ai meccanismi utilizzati per implementare la tolleranza ai guasti.


Impaginato originale...


Clicca per ingrandire... Clicca per ingrandire...
Clicca per ingrandire... Clicca per ingrandire...
Clicca per ingrandire...  
Clicca per ingrandire...  

Articolo pubblicato su www.digiTANTO.it - per ulteriori informazioni clicca qui