S.E.S.A.M.E
Transcript
S.E.S.A.M.E
S.E.S.A.M.E Support for Emulation of Services and Applications in Mobile Environments Abstract In questo documento si presenterà SESAME, un emulatore per le WLAN (Wireless Local Area Network), pensato per essere usato nelle fasi di sviluppo di applicazioni e servizi distribuiti che sfruttano le reti WLAN per la comunicazione. In particolare, SESAME realizza un supporto per il livello applicativo che consente di creare una MANET, disponendo i nodi a piacere dell’utente, permettendo quindi di testare un’applicazione distribuita in modo semplice e veloce avendo a disposizione sulla stessa macchina più istanze dell’applicazione su JVM distinte. SESAME non limita però il testing all’utilizzo di un solo calcolatore, ma se si necessita di una maggiore potenza di calcolo, i nodi virtuali della MANET possono facilmente essere disposti su più calcolatori. In questa relazione verranno esposti i dettagli progettuali ed implementativi che hanno portato alla realizzazione di SESAME. 1. Introduzione Il testing di applicazioni in ambienti reali WLAN è reso difficile dal fatto che il mezzo trasmissivo wireless è difficile da controllare e a volte interferenze possono perturbare i risultati sperimentali. Inoltre, le difficoltà aumentano se occorre tenere conto anche della mobilità dei nodi, in quanto bisognerebbe monitorare e dirigere movimenti di tutti i nodi della rete considerata. Per lo studio delle WLAN e per il testing delle applicazioni si fa quindi uso di simulatori e di modelli analitici. I modelli analitici sono tecniche astratte che non consentono di fare delle misure oggettive di quanto accade nella rete, ma consentono solo di realizzare delle previsioni relative al comportamento generale del sistema. La simulazione, invece, è più vicina alla realtà e consente di raccogliere dati sul comportamento della rete e dei nodi una volta stabilito il modello della rete. Possiamo distinguere due tipi di approcci alla simulazione: l’emulazione di rete e la simulazione di rete. I simulatori sono dei componenti software che, dato un modello della rete ne simulano il comportamento permettendo di ricavare dei risultati sperimentali. Gli emulatori,invece, effettuano una simulazione usando le applicazioni simili a quelle che saranno usate dagli utenti finali. Le prove avvengono collegando fisicamente i nodi su cui gira l’applicazione ad un nodo centrale che si occupa di simulare la rete, permettendo così di ricavare dei dati sperimentali molto vicini agli scenari reali. Gli strumenti esistenti, sia nella categoria dei simulatori che in quella degli emulatori, consentono di raccogliere dati sperimentali molto accurati, ma hanno il difetto di essere spesso difficili da configurare ed utilizzare, non fornendo quindi un supporto adeguato allo sviluppo ed alle prime fasi di testing di applicazioni distribuite. SESAME si colloca nella categoria degli emulatori ed ha come obiettivi la semplicità d’uso, la portabilità multipiattaforma e la facile integrabilità con le applicazioni da testare. L’emulatore è infatti scritto in Java e occorrono poche modifiche al codice dell’applicazione per utilizzarlo, inoltre la creazione della topologia di rete è facilitata dall’interfaccia grafica attraverso cui è possibile spostare i nodi a piacere e visualizzare le proprietà associate ai nodi presenti. SESAME fornisce inoltre un supporto per lo studio delle applicazioni in scenari in cui è presente mobilità dei nodi: sono stati implementati il Random walk model e il boundless simulation due modelli di mobilità tra i più usati nelle simulazioni delle WLAN. Nel primo capitolo della relazione verranno messi a confronto alcuni simulatori ed emulatori esistenti, nel secondo capitolo verrà invece esplorata l’architettura di SESAME concentrando l’attenzione sulla interfaccia con l’applicazione, infine verranno discussi i test effettuati e i possibili sviluppi futuri. 2. Simulatori ed emulatori Il termine “simulazione” definisce il processo di modellazione di un sistema reale in modo da poterlo studiare in diverse configurazioni di utilizzo. I simulatori possono essere divisi in due grandi grandi categorie in base al metodo usato per gestire la simulazione: event-driven, time-driven. Della categoria event-driven fanno parte tutti quei simulatori che sono sensibili allo scatenarsi di eventi sulla rete. In base al tipo di evento considerato possiamo suddividerli ulteriormente in: 1. packet-driven: in questo tipo di simulazione ogni pacchetto trasmesso sulla rete genera un evento. Questo metodo è quello più vicino al comportamento delle reti reali, tuttavia il numero di eventi generati può essere molto alto rendendo la simulazione non computabile su macchine poco potenti. 2. fluid: per risolvere i problemi computazionali impliciti nel metodo precedente, fluid usa un diverso modello ad eventi. Invece di generare un evento per ogni pacchetto scambiato, il sistema viene considerato ad un livello di astrazione più alto: la trasmissione dei dati è considerata come un flusso descritto dal loro bit rate. I soli eventi considerati sono le variazioni di bit rate di un dato flusso. Questa metodologia ha però due svantaggi: il livello di astrazione più alto necessita di alcuni studi matematici preliminari prima dell’implementazione di tipi di traffico o politiche di rete, inoltre l’interazione tra più flussi può far aumentare drasticamente il numero di eventi generati (ripple effect). E’ stato dimostrato in [1] che per politiche con molta interazione tra i flussi il numero di eventi generato è molto superio- re rispetto al metodo packet-driven. Inoltre possiamo notare che raddoppiando il volume di traffico e utilizzando un simulatore fluid non si notano variazioni significative nei tempi della simulazione. Nel caso di simulatori time driven la simulazione è tempo discreta: il tempo è diviso in piccoli intervalli regolari e lo stato del sistema evolve solo in dati istanti temporali della scala dei tempi discretizzata, influenzando la precisione della simulazione. Il vantaggio principale della simulazione time-driven è l’uso facilitato di architetture parrallele: tutti i processori possono sincronizzarsi al termine di ogni time step. Realizzare tali simulatori con algoritmi paralleli può aumentarne drasticamente le performance. I simulatori di rete più usati sono NS2[2] e GlomOSim[3] di cui esiste anche una versione commerciale. In generale i simulatori non possono essere usati con i protocolli di rete e le applicazioni reali ma modificando l’applicazione per l’uso nel simulatore in quanto basano la simulazione su un modello astratto della rete. Durante lo sviluppo e il testing di applicazioni si producono molte versioni del software che devono essere tutte trasportate dall’ambiente reale a quello simulato. Oltre alle difficoltà che potrebbero sorgere nel passare dall’ambiente reale a quello simulato, la maggiorparte dei simulatori non forniscono un punto di vista real time della simulazione in quanto si appoggiano su macchine virtuali. Per ovviare a questi problemi occorre utilizzare dei simulatori di rete real time o emulatori di rete più vicini alla realtà e con un ambiente più controllato, che consentano agli sviluppatori di creare delle topologie di rete che sarebbero difficili da ottenere con dei test nel mondo reale, o che permettano di realizzare dei test real time attraverso vari protocolli. La maggior parte degli emulatori di rete forniscono la possibilità di fornire ritardi differenti, di simulare la perdita di pacchetti e funzionalità di accodamento per simulare diversi canali di comunicazione e diversi tipi di rete in modo da poter raccogliere dati in diverse condizioni di utilizzo della rete. Tra gli emulatori esistenti si distinguono NetEmulator[4] ed Itheon NetEmulator[5]. Gli emulatori esistenti forniscono delle API non standard per la comunicazione: l’applicazione dovrà essere modificata ad-hoc per l’emulatore portando un allungamento dei tempi di sviluppo. Occorre quindi uno strumento che sia facile da configurare ed che al contempo renda immediato il passaggio da ambiente reale ad ambiente simulato, riducendo drasticamente i costi di apprendimento del sistema e abbassando i tempi di sviluppo dell’applicazione. SESAME nasce proprio per venire incontro a queste esigenze fornendo un ambiente di emulazione molto semplice da usare e configurare. 3. SESAME SESAME fa parte della categoria degli emulatori di rete, infatti non si occupa di simulare lo stack di protocolli o il mezzo trasmissivo, ma si occupa solo di simulare una data topologia di rete e la mobilità dei nodi, cercando di fornire un supporto computazionalmente leggero e flessibile che consenta di testare rapidamente applicazioni e servizi distribuiti che sfruttano le reti wireless ad-hoc, consentendo allo sviluppatore di emulare una MANET mettendo in esecuzione su una o più macchine più istanze del servizio o dell’applicazione di rete da testare. SESAME, inoltre, si pone come obiettivo la semplicità d’uso relativa sia all’interfaccia utente sia all’integrazione con l’applicazione da testare: è dotato, infatti, di una GUI intuitiva, che consente di creare topologie di rete a piacere e di eseguire dei test anche tenendo conto della mobilità dei nodi, ed è integrabile semplicemente inserendo e usando una libreria nell’applicazione da testare. SESAME integra al suo interno log4j[6] in modo da generare automaticamente dei log relativi al traffico di rete e agli eventi principali che avvengono durante la simulazione. Per quanto riguarda le reti emulate, SESAME consente l’emulazione di MANET basate su UDP i cui nodi comunicano in unicast o in broadcast. Nei seguenti sottoparagrafi verrà discussa l’architettura del sistema e l’interazione fra le sue parti e con il livello applicativo. 3.1 Architettura del sistema Prima di esporre nel dettaglio il funzionamento di SESAME occorre esplorare la sua architettura e capire le interconnessioni tra le varie parti. SESAME è formato essenzialmente da due strati: l’ApplicationInterface e il Server sulle quali poggia il livello applicativo (fig. 3.1). fig 3.1a - Architettura server fig 3.1b - Architettura application interface L’architettura di SESAME è basata sul modello client/server in cui i nodi simulati rappresentano i client mentre il server è il nucleo di SESAME dove viene eseguita l’emulazione effettiva della rete. Tutti i client ed il server girano su JVM distinte e possono essere in esecuzione sulla stessa macchina o su macchine diverse. L’application interface ha il compito di rendere possibile l’uso del simulatore alle applicazioni, fornendo un’interfaccia compliant con le DatagramSocket di Java in modo da facilitare il passaggio della applicazione dall’ambiente reale all’ambiente emulato e viceversa e deve, quindi, essere presente su tutti i client della rete. Il server invece si occupa dell’emulazione di rete vera e propria offrendo una GUI intuitiva e una rapida configurazione dell’ambiente di lavoro. Il server esegue l’emulazione utilizzando i servizi mostrati in fig 3.1: • comunication services: sono i servizi di più basso livello. Il loro compito è quello di gestire l’invio e la ricezione di datagrammi applicativi (unicast e broadcast) e di controllo da parte del server; • virtual network manager: gestisce la rete virtuale creata dall’utente su cui viene eseguita l’emulazione. Questo servizio si occupa della gestione della topologia della rete e degli indirizzi IP virtuali: ad ogni nodo su cui gira l’applicazione da testare viene assegnato un indirizzo IP fittizio che verrà usato dai nodi della rete per comunicare. Tale virtualizzazione è necessaria in quanto si vuole rendere possibile l’emulazione di una rete avendo a disposizione più nodi su una stessa macchina e ogni nodo deve essere caratterizzato da un indirizzo IP diverso, quindi occorre usare delle socket virtuali che effettuino la traduzione degli indirizzi sia in fase di invio che in fase di ricezione; • virtual routing manager: questo livello gestisce il routing dei pacchetti applicativi unicast e broacast nella rete virtuale. Per i pacchetti unicast si occupa di verificare la raggiungibilità del destinatario attraverso il calcolo dello shortest path tramite l’algoritmo Dijkstra[7]: se il nodo è raggiungibile allora il pacchetto verrà inviato al nodo destinatario altrimenti verrà scartato. I pacchetti di broadcast vengono invece inviati a tutti i vicini direttamente visibili dal mittente. Al fine di ottimizzare i tempi di calcolo del percorso minimo, tale servizio usa una tabella di routing in cui memorizza i percorsi tra i nodi della rete virtuale; • movement manager: questo servizio si occupa della simulazione del movimento dei nodi utilizzando due modelli di mobilità: random walk model e boundless simulation area mobility model[8]. Durante il movimento dei nodi mantiene coerenti le strutture dei servizi sottostanti; • GUI: è l’interfaccia utente attraverso cui è possibile accedere a tutte le funzionalità del simulatore: è possibile creare la topologia desiderata spostando con il mouse i nodi, è possibile ottenere informazioni relative ad un nodo facendo doppio click sul nodo desiderato o è possibile eseguire gli algoritmi di mobilità implementati. In SESAME i nodi non partecipano attivamente al routing dei pacchetti applicativi e il movimento viene simulato solo dal server, quindi i servizi presenti nell’application interface sono solo quelli necessari per la comunicazione tra i nodi e il server: • comunication services: sono due servizi distinti: uno si occupa della gestione dell’invio e della ricezione dei pacchetti applicativi, l’altro dei pacchetti di controllo; • virtual network manager: il suo ruolo fondamentale è quello della creazione e gestione delle socket virtuali: l’applicazione si interfaccia con esso per creare ed usare le socket virtuali. Si occupa in fase iniziale di negoziare con il server l’IP virtuale e, durante la vita dell’applicazione, di tenere aggiornato il server sui cambiamenti del nodo in particolare creazione e chiusura di socket e uscita del nodo dal sistema. L’application interface è quindi pensato per essere un componente leggero dal punto di vista delle risorse computazionali impiegate e facilmente integrabile dall’applicazione. 3.2 Interazione L’interazione tra l’interfaccia applicativa e il server che effettua l’emulazione della rete, è basata su un protocollo a scambio di messaggi in cui vengono scambiati sia messaggi provenienti dall’applicazione sovrastante che messaggi di controllo e aggiornamento dello stato dei nodi. In particolare si tratta di un interazione basata sul modello client/server in cui l’emulatore è il server e i nodi della rete sono i client. Possiamo distinguere diverse fasi nella vita di un nodo in cui avviene l’interazione tra il lato applicativo e il server: • fase di join: è il momento in cui l’applicazione decide di comunicare creando la sua prima socket. In questa fase l’application interface si occupa di comunicare al server la comparsa di un nuovo nodo inviando una richiesta di join. A tale richiesta il server risponderà inviando un numero di identificazione (ID del nodo) da cui verrà ricavato l’indirizzo IP virtuale del nodo stesso. In particolare gli indirizzi avranno la forma “192.168.1.ID”. fig. 3.2 - fase di join • creazione di una socket: al momento della creazione di una nuova socket l’interfaccia applicativa aggiorna il server inviando un messaggio di PortUpdate in cui specifica il numero di porta della nuova socket e il nodo di provenienza in modo da tenere aggiornate le strutture dati del server. • invio di pacchetti applicativi: l’applicazione una volta create le sue socket procederà all’invio di pacchetti unicast o broadcast. Ogni pacchetto applicativo viene inserito in un messaggio dall’application interface e inviato al server che, una volta verificata la raggiungibilità del destinatario, gli invierà il pacchetto. Prima dell’invio del pacchetto al destinatario il server invierà un messaggio di acknowledge al mittente in modo da garantire la ricezione del messaggio. • ricezione di pacchetti applicativi: anche la ricezione dei pacchetti applicativi passa attraverso l’interfaccia applicativa. All’atto della ricezione di un messaggio applicativo da parte del server, l’application interface ricrea il pacchetto originariamente inviato dal mittente e lo passa al livello applicativo. fig. 3.3 - Invio/ricezione datagrammi applicativi • chiusura di una socket e kill del nodo: quando l’applicazione effettua la chiusura di una socket l’interfaccia applicativa comunica al server tale evento. Quando viene chiusa anche l’ultima socket, viene comunicato al server un evento di kill con cui il verrà cancellato il nodo. Tali comunicazioni avvengono inviando dei PortUpdateMessage contenenti l' identificativo del nodo e il numero di porta da chiudere. fig. 3.4 - kill di un nodo Nelle fasi di join, di chiusura di una Socket e di kill di un nodo, vista l’importanza del corretto arrivo al server dei messaggi, l’applicationInterface aspetta di ricevere l’acknowledge da parte del server prima di proseguire con le altre operazioni. Se il server non ricevesse un messaggio di join, infatti, non registrerebbe il nodo e questo quindi non potrebbe comunicare, se invece non ricevesse un messaggio di creazione di una socket scarterebbe tutti i messaggi diretti a quella socket, infine non ricevendo messaggi di chiusura di una socket continuerebbe ad inviare messaggi al nodo che non è più in ascolto su quella socket, falsando quindi i risultati sperimentali della simulazione. 4.Application Interface L’application interface è la parte di SESAME più a contatto con il livello applicativo, fornisce l’interfaccia che permette all’applicazione di comunicare e mantiene aggiornato il server relativamente ai cambiamenti del nodo. Al fine di consentire la comunicazione tra i nodi l’ApplicationInterface fornisce un’interfaccia compliant a quella della classe DatagramSocket di Java facilitando il passaggio da ambiente reale ad ambiente emulato e viceversa (fig. 4.1). fig. 4.1 - Interfaccia Avendo a disposizione l’interfaccia mostrata in fig. 4.1, lo sviluppatore per passare da ambiente reale ad ambiente simulato non dovrà fare altro che includere la libreria ApplicationInterface e sostituire le DatagramSocket con le ApplicatioSocket presenti nella libreria continuando ad usare gli stessi metodi. Attraverso quest’interfaccia l’applicazione può accedere ai servizi forniti da SESAME lato client in modo da comunicare con gli altri nodi. In particolare l’applicazione usa direttamente i servizi del virtual network manager (fig. 3.1) per creare le ApplicationSocket tramite una factory: una volta create, queste verranno usate attraverso l’interfaccia in fig. 4.1. Il virtual network manager consente al nodo simulato di ottenere un IP virtuale all’inizio della simulazione, di comunicare con gli altri nodi permettendo all’applicazione l’invio e la ricezione di messaggi unicast e broadcast, mantiene aggiornato il server sullo stato del nodo. I comunication services si occupano della comunicazione effettiva: il virtual network manager per poter inviare il pacchetto al server usa il comunication service relativo ai pacchetti applicativi mentre per tenere aggiornato il server usa il servizio relativo ai messaggi di controllo. A questo livello viene gestita l’attesa dell’acknowledge da parte del server e la gestione dei reinvii dei messaggi in caso di mancato acknowledge: una volta inviato il messaggio contenente il pacchetto applicativo al server, viene generato un thread che attende l’acknowledge e gestisce il reinvio del messaggio. 5. Esempio di sviluppo di un’applicazione In questo capitolo verrà mostrato l’utilizzo dell’ ApplicationInterface per mezzo una semplice applicazione d’esempio e verrà mostrato il percorso del datagramma appliccativo tra i vari servizi dell’application interface. Tale applicazione, scritta in Java, creerà come prima cosa due ApplicationSocket e ne userà una per inviare e una per ricevere messaggi. Il primo passo nello sviluppo di un’applicazione che verrà testata in SESAME è la scrittura dei file di configurazione per il server e per i nodi. Ogni nodo ha un file di configurazione che contiene le seguenti informazioni: • radius: è il raggio d’azione del nodo; • address: l’indirizzo IP della macchina su cui si trova il nodo; • In_Port: il numero della porta di input; • Out_Port: il numero della porta di output; • initial_position: le coordinate della posizione iniziale del nodo in SESAME. Oltre al file di configurazione del nodo occorre scrivere il file server.txt che contiene le informazioni relative all’indirizzo alla porta su cui è in ascolto il server. I file di configurazione del nodo e del server verranno letti al momento della creazione della prima socket dalla SocketFactory. La creazione di una ApplicationSocket avviene sempre attraverso l’invocazione del metodo statico SocketFactory.getNewSocket(String fileName,int port,InetAddress address) i cui parametri rappresentano rispettivamente il nome del file di configurazione del nodo il numero di porta virtuale da associare all’ApplicationSocket e l’indirizzo reale del nodo. Una volta informato il server della nuova ApplicationSocket creata, il metodo la restituisce all’applicazione che ora potrà iniziare ad usarla come una normale DatagramSocket. Il seguente blocco di codice mostra la creazione di due ApplicationSocket e l’invio di un DatagramPacket: ApplicationSocket as1=SocketFactory.getNewSocket(“conf.txt”,8000); ApplicationSocket as2=SocketFactory.getNewSocket(“conf.txt”,8001); ... ... DatagramPacket packet=new DatagramPacket(); as1.send(packet); Prima di essere inviato, il datagramma viene inserito in un messaggio che contiene informazioni relative al mittente (indirizzo virtuale e porta virtuale) e al destinatario. In base a questi dati il server sarà in grado di individuare i due nodi e di sapere se essi possono comunicare tra loro. I messaggio creato viene affidato al WaitAckThread che si occupa dell’invio e dell’attesa di un messaggio di acknowledgement da parte del server. La ApplicationSocket as2 potrebbe essere usata, ad esempio, per la ricezione di pacchetti nel modo seguente: as2.receive(packet); l’applicazione rimarrà bloccata in attesa dell’arrivo di un datagramma. In particolare l’application interface ha un thread sempre in attesa su una socket: al momento della ricezione di un messaggio, questo verrà passato alla socket virtuale cui corrisponde il numero di porta indicato nel messaggio che provvederà a formare un datagramma da fornire all’applicazione. Per quanto riguarda la ricezione dei messaggi broadcast occorre configurare la ApplicationSocket usando il metodo setBroadcast(broadcast:boolean) nel modo seguente: as2.setBroadcast(true/false); lo stato del broadcast può essere controllato usando il metodo getBroadcast() che restituisce un valore booleano. All’arrivo di un messaggio di broadcast l’application interface lo inserirà in tutte le code delle socket virtuali abilitate a ricevere messaggi di broadcast. E’ possibile, inoltre, impostare un tempo di timeout scaduto il quale la ApplicationSocket si sblocca dalla receive e lancia un’eccezione: as2.setSoTimeout(1000); try{ as2.receive(packet); }catch(SocketTimeOutException){ ... } Nell’esempio se il messaggio non arriva entro 1 secondo viene lanciata l’eccezione. Sono stati, inoltre, implementati i metodi connect(address,port) e disconnect() che consentono alla ApplicationSocket di ricevere solo i pacchetti provenienti dall’indirizzo e dalla porta specificati; invocando invece la disconnect() la ApplicationSocket riprenderà a ricevere i pacchetti da qualsiasi mittente. 6. Misurazioni In questo paragrafo verranno illustrate le misurazioni effettuate sull’interfaccia applicativa dell’emulatore. Innanzi tutti è stato misurato l’occupazione di memoria di hard disk e run time: lo spazio occupato su HD della libreria applicationInterface inclusi i file di configurazione del nodo è pari a circa 500 kB, mentre la memoria a run time è pari circa a 11.600 kB inclusa la JVM che occupa 7.200 kB. La seconda fase delle misure è relativa alla dimensione dei pacchetti di controllo e all’overhead sui pacchetti applicativi dovuto all’uso di SESAME. La tabella 6.1 mostra le dimensioni dei messaggi di controllo che il server e l’applicazionInterface si scambiano per mantenersi aggiornati. Tipo messaggio Dimensione[byte] UpdateMessage: addNode 703 UpdateMessage: ackReg 696 PortUpdateMessage:add 127 PortUpdateMessage:del 127 PortUpdateMessage:kill 128 PortUpdateMessage:ackPort 131 PortUpdateMessage:ackDel 130 PortUpdateMessage:ackKill 131 tab. 6.1 - Dimensione messaggio di controllo L’overhead sui messaggi applicativi invece è di 393 byte per i messaggi di unicast e 361 per quelli di broadcast. 7. Conclusioni e sviluppi futuri Lo sviluppo di applicazioni in ambiente MANET apre numerose problematiche relative ai test di applicazioni e servizi: il mezzo trasmissivo potrebbe essere esposto ad interferenze e lo sviluppatore potrebbe non avere a disposizione il numero di nodi necessario per eseguire dei test. Inoltre in un scenario MANET occorre spesso tenere in considerazione la mobilità dei nodi introducendo altre difficoltà nell’esecuzione dei test. Abbiamo visto come sia possibile risolvere questi problemi utilizzando dei simulatori o degli emulatori di rete e le loro problematiche di utilizzo. Tali strumenti permettono di simulare diverse topologie di rete e diversi protocolli consentendo di ottenere risultati sperimentali utilizzando uno o pochi pc. SESAME è l’emulatore di rete sviluppato in questo progetto che consente di emulare MANET con topologie scelte dall’utente i cui nodi comunichino in unicast e broadcast. SESAME fornisce un supporto alle applicazione e ai servizi da testare facilmente integrabile attraverso cui è possibile ricavare dati sperimentali relativi alla rete in modo semplice e veloce cercando di venire incontro alle esigenze degli sviluppatori I promettenti risultati ottenuti utilizzando SESAME aprono nuovi possibili sviluppi dell’emulatore introducendo l’emulazione di reti ad-hoc in modalità infrastruttura o estendendo SESAME in modo da emulare anche il protocollo TCP. 8. References [1] Benyuan Liu, Daniel R. Figuerido, Yang Guo, Jim Kurose and Don Towlsey. A study of networks simulation efficiency: Fluid simulation vs. packet-level simulation. [2] http://nsnam.isi.edu/nsnam/index.php/Main_Page [3] http://pcl.cs.ucla.edu/projects/glomosim/ [4] http://www.openchannelfoundation.org/projects/NetEmulator/ [5] http://www.sygnusdata.co.uk/partners_itheon_network_emulator.htm [6] http://logging.apache.org/log4j/ [7] http://it.wikipedia.org/wiki/Algoritmo_di_Dijkstra [8] Tracy Camp, Jeff Boleng, Vanessa Davies. A Survey of Mobility Models for Ad Hoc Network Research