Onion Information
Povezivanje čvorova u simulaciji računalnih mreža - GASERI
Ovdje je to čvor sa indeksom 0 odnosno prvi čvor unutar kontejnera nodes . Za klijentsku aplikaciju je potrebno zakazati pokretanje i zaustavljanje u određenim trenutcima metodama Start() i Stop() . Na kraju ne preostaje ništa drugo nego po...
Onion Details
Page Clicks: 0
First Seen: 03/15/2024
Last Indexed: 10/23/2024
Onion Content
Preskoči na sadržaj Povezivanje čvorova u simulaciji računalnih mreža Jednostavna simulacija s izravno povezanim čvorovima U ovom primjeru stvorit ćemo dva čvora; instalirat ćemo komunikacijske uređaje i podršku za potrebne protokole i uspostaviti komunikaciju korištenjem UDP-a između klijentske aplikacije na prvom čvoru i poslužiteljske na drugom. Na početku programa uključujemo zaglavlja pojedinih modula simulatora ns-3 naredbom #include<> . Svi simboli koje ns-3 koristi su unutar imenika ns3 ; zbog toga je potrebno uključiti korištenje tog imenika kako bi pojednostavili pisanje koda (u protivnom bilo bi potrebno pisati, primjerice, ns3::NodeContainer umjesto NodeContainer i ns3::PointToPointHelper umjesto PointToPointHelper ). #include #include #include #include #include using namespace ns3; Cjelokupan program nalazi se unutar funkcije main() , što je i realno za očekivati zbog njegove jednostavnosti. Zanemarimo za sada linije LogComponentEnable ( "UdpEchoClientApplication" , LOG_LEVEL_INFO ); LogComponentEnable ( "UdpEchoServerApplication" , LOG_LEVEL_INFO ); koje se tiču logginga. Za sada je dovoljno znati da su one potrebne da bi simulacija dala ikakav izlaz na ekran. Na počeku simulacije stvaramo objekt nodes koji je instanca klase NodeContainer ( dokumentacija ). Zatim u tom objektu stvaramo dva čvora metodom Create() . NodeContainer nodes ; nodes . Create ( 2 ); PointToPointHelper ( dokumentacija ) je pomoćnik (ili čarobnjak kako možemo vidjeti u mnogim programima) koji stvara sve što je potrebno za rad veze tipa točka-do-točke između dva čvora (stvara mreže uređaje, dodaje ih čvorovima i povezuje ih kanalom). Stvaramo instancu te klase i nazivamo ju pointToPoint, a zatim metodom SetDeviceAttribute() postavljamo atribute budućih uređaja. Vrijednosti parametara su tipa znakovni niz i zapravo eksplicitno govore o čemu se radi: konkretno, atribut DataRate je brzina prijenosa podataka i iznosi "5Mbps" . Metoda SetChannelAttribute() postavlja atribute same veze. Delay je zadržavanje veze i ono iznosi "2ms" . Funkciju StringValue koristimo da bismo pretvorili eventualni varijable tipa const char * (podaci "5Mbps" i "2ms" su tog tipa, kao i svi ostali znakovni nizovi navedeni u izvornom kodu) u tip StringValue koji metode SetDeviceAttribute i SetChannelAttribute primaju kao drugi parametar. PointToPointHelper pointToPoint ; pointToPoint . SetDeviceAttribute ( "DataRate" , StringValue ( "5Mbps" )); pointToPoint . SetChannelAttribute ( "Delay" , StringValue ( "2ms" )); NetDeviceContainer ( dokumentacija ) je klasa koja služi kao kontejner za mrežne uređaja. Kreiramo instancu devices , a zatim metodom Install() na objekt nodes instaliramo uređaje na čvorove i istovremeno ih pohranjujemo u kontejner da lakše s njima baratamo. (Uočite da je u dokumentaciji navedena metoda Get() koja nam olakšava dohvaćanje elementa kontejnera.) NetDeviceContainer devices ; devices = pointToPoint . Install ( nodes ); InternetStackHelper ( dokumentacija ) je još jedan u nizu pomoćnika koje koristimo. Metodom Install() na objekt nodes instaliramo TCP/UDP i IP funkcionalnost na čvorove koji su unutar tog kontejnera. InternetStackHelper stack ; stack . Install ( nodes ); Ipv4AddressHelper ( dokumentacija ) je pomoćnik koji dodjeljuje IPv4 adrese mrežnim uređajima (podsjetite se zašto su IPv4 adrese vezane za mrežne uređaje, a ne za čvorove). SetBase() je metoda koja prima dva parametra: prvi parametar je adresa, a drugi maska podmreže. Ipv4AddressHelper address ; address . SetBase ( "10.1.1.0" , "255.255.255.0" ); Ipv4InterfaceContainer ( dokumentacija ) je kontejner za IPv4 sučelja na mrežnim uređajima. Metoda Assign() klase Ipv4AddressHelper dodjeljuje adrese uređajima unutar kontejnera devices . Ipv4InterfaceContainer interfaces ; interfaces = address . Assign ( devices ); UdpEchoServerHelper ( dokumentacija ) je pomoćnik. Kod stvaranja instance echoServer prosljeđuje se jedan parametar; iz dokumentacije se može iščitati da se radi o broju vrata (u ovom slučaju 9) na kojima će komunikacija biti omogućena. UdpEchoServerHelper echoServer ( 9 ); Zatim kreiramo serversku aplikaciju. ApplicationContainer je još jedan u nizu kontejnera u koje spremamo određene elemente simulacije; instancu nazivamo serverApps . Metoda Install() dobiva kao parametar objekt tipa Node , jer je to povratni tip metode Get() objekta nodes . Pritom pripazimo na indeksiranje; radi se o drugom elementu, obzirom da brojanje počinje od 0. Start() i Stop() su metode koje zakazuju vrijeme pokretanja i zaustavljanja rada serverske aplikacije, a kao parametre primaju sekunde. Ono na što treba obratiti pozornost je da se serverska aplikacija pokreće prije i gasi nakon pokretanja klijentske aplikacije, osim u slučajevima gdje baš želimo testirati specifično ponašanje. ApplicationContainer serverApps = echoServer . Install ( nodes . Get ( 1 )); serverApps . Start ( Seconds ( 1.0 )); serverApps . Stop ( Seconds ( 10.0 )); UdpEchoClientHelper ( dokumentacija ) imena echoClient koristimo na sličan način za kreiranje klijentske aplikacije. Parametri koje prima kod stvaranja su adresa i vrata poslužiteljske aplikacije. Ovdje je to IPv4 sučelje drugog čvora ( interfaces.GetAddress(1) ) i vrata 9. Zatim postavljamo razne atribute klijentske aplikacije. MaxPackets je broj paketa koje šalje klijentska aplikacija i očekuje vrijednost tipa UintegerValue (vrijednost tipa nepredznačeni cijeli broj) te je potrebno napraviti pretvorbu. Interval je razmak između slanja svakog pojedinog paketa, zapravo frekvencija slanja, vrijednost tipa TimeValue . Ovdje je vrijednost postavljena na 1 sekundu što znači da će se paketi slati u pravilnom vremenskom intervalu od jedne sekunde. PacketSize je veličina paketa, također vrijednost tipa UintegerValue . UdpEchoClientHelper echoClient ( interfaces . GetAddress ( 1 ), 9 ); echoClient . SetAttribute ( "MaxPackets" , UintegerValue ( 1 )); echoClient . SetAttribute ( "Interval" , TimeValue ( Seconds ( 1.0 ))); echoClient . SetAttribute ( "PacketSize" , UintegerValue ( 1024 )); Alternativno, mogli smo IPv4 adresu poslužitelja navesti i eksplicitno. UdpEchoClientHelper echoClient ( Ipv4Address ( "10.1.1.2" ), 9 ); Kao i serversku aplikaciju i klijentsku instaliramo na određeni čvor. Ovdje je to čvor sa indeksom 0 odnosno prvi čvor unutar kontejnera nodes . Za klijentsku aplikaciju je potrebno zakazati pokretanje i zaustavljanje u određenim trenutcima metodama Start() i Stop() . ApplicationContainer clientApps = echoClient . Install ( nodes . Get ( 0 )); clientApps . Start ( Seconds ( 2.0 )); clientApps . Stop ( Seconds ( 10.0 )); Na kraju ne preostaje ništa drugo nego pokrenuti simulator sa metodom Run() . Simulator :: Run (); Uočite da se ova metoda pokreće na drugačiji način, odnosno da nema instancu klase. Radi se o takozvanoj statičkoj klasi koja se ne može instancirati; time se nećemo ovdje nećemo više baviti (uzimati ćemo da to jednostavno radi tako), obzirom da se o tome više govori na kolegiju Objektno orijentirano programiranje. Nakon što je simulator završio sa radom valja počistiti memoriju, a to činimo metodom Destroy() . Dvije potonje linije koda zapravo slijede jedna drugu iz razloga što u samom simulatoru određujemo vrijeme trajanja simulacije definicijom topologije i zakazivanjem događaja. Simulacija se u cijelosti izvršava pozivom metode Run() pa tek nakon završetka izvođenje programa dolazi do linije u kojoj se poziva metoda Destroy() . Simulator :: Destroy (); Cjelokupni kod primjera je /* * UdpEchoClient UdpEchoServer * 10.1.1.0 10.1.2.0 * n1 ------------------n2------------------n3 * point-to-point */ #include #include #include #include #include using namespace ns3 ; int main () { LogComponentEnable ( "UdpEchoClientApplication" , LOG_LEVEL_INFO ); LogComponentEnable ( "UdpEchoServerApplication" , LOG_LEVEL_INFO ); NodeContainer allNodes , nodes12 , nodes23 ; allNodes . Create ( 3 ); nodes12 . Add ( allNodes . Get ( 0 )); nodes12 . Add ( allNodes . Get ( 1 )); nodes23 . Add ( allNodes . Get ( 1 )); nodes23 . Add ( allNodes . Get ( 2 )); PointToPointHelper pointToPoint ; pointToPoint . SetDeviceAttribute ( "DataRate" , StringValue ( "5Mbps" )); pointToPoint . SetChannelAttribute ( "Delay" , StringValue ( "2ms" )); NetDeviceContainer devices12 , devices23 ; devices12 = pointToPoint . Install ( nodes12 ); devices23 = pointToPoint . Install ( nodes23 ); // pointToPoint.EnablePcapAll ("vjezba-udp-echo-neizravna-veza"); InternetStackHelper stack ; stack . Install ( allNodes ); Ipv4AddressHelper address ; address . SetBase ( "10.1.1.0" , "255.255.255.0" ); Ipv4InterfaceContainer interfaces12 = address . Assign ( devices12 ); address . SetBase ( "10.1.2.0" , "255.255.255.0" ); Ipv4InterfaceContainer interfaces23 = address . Assign ( devices23 ); Ipv4GlobalRoutingHelper :: PopulateRoutingTables (); UdpEchoServerHelper echoServer ( 9 ); ApplicationContainer serverApps = echoServer . Install ( allNodes . Get ( 2 )); serverApps . Start ( Seconds ( 1.0 )); serverApps . Stop ( Seconds ( 10.0 )); UdpEchoClientHelper echoClient ( interfaces23 . GetAddress ( 1 ), 9 ); echoClient . SetAttribute ( "MaxPackets" , UintegerValue ( 1 )); echoClient . SetAttribute ( "Interval" , TimeValue ( Seconds ( 1.0 ))); echoClient . SetAttribute ( "PacketSize" , UintegerValue ( 1024 )); ApplicationContainer clientApps = echoClient . Install ( allNodes . Get ( 0 )); clientApps . Start ( Seconds ( 2.0 )); clientApps . Stop ( Seconds ( 10.0 )); Simulator :: Run (); Simulator :: Destroy (); return 0 ; } Praćenje i analiza simuliranog mrežnog prometa Sve dosad opisano je dovoljno da bi aplikacija radila. Međutim, iskoristit ćemo još jednu metodu objekta tipa PointToPointHelper , a to je EnablePcapAll() koja čini da se stvaraju snimke mrežnog prometa (engl. packet capture , kraće pcap ), odnosno datoteke koje sadrže simulirane pakete. Ta metoda prima niz znakova koji će biti prefiks imena datoteka koje će stvoriti. Važno je da se ova metoda pozove nakon svih poziva Install() metode nad objektom pointToPoint , što je najlakše napraviti tako da pozovete metodu neposredno prije samog pokretanja simulacije sa Simulator::Run() . Time se izbjegava mogućnost nepravovremenog poziva metode koja u tom slučaju neće generirati ništa ili će pak generirati pogrešan izvještaj. Datoteka koju generira ova metoda bit će smještena u direktoriju gdje se događa kompajliranje vašeg programskog koda. U slučaju da ste kao odredište spremanja datoteka projekta odabrali vaš kućni direktorij (u virtualnoj mašini to je /home/student ), a projekt nazvali ga rm2-vj1-primjer1i , direktorij u kojem se nalazi pcap datoteke zove se rm2-vj1-primjer1i-build- . Taj direktorij, sadrži izvršnu datoteku vašeg projekta, datoteke s objektnim kodom ( *.o ) i pcap datoteke koje imaju prefiks u imenu koji ste zada...