Inhoudsopgave
Samenvatting
Dit is de opgave voor het project van het vak ``Structuur van Computerprogramma's II'' voor de tweede zittijd van het academiejaar 2005-2006.
Deze tekst is ook beschikbaar in postscript (stru2-2005.ps) en pdf (stru2-2005.pdf) formaat.
Het programma maakt gebruik van de normale internet protocollen en standaarden: TCP/IP, DNS. Zeer summier:
Een machine op het net heeft een numeriek adres, meestal voorgesteld als een rij van 4 bytes. Bvb. is 134.184.65.2 het internet adres van tinf2.
D.m.v. de DNS service kunnen een of meerdere namen geassocieerd worden met een internet adres. Bvb. is tinf2.vub.ac.be de officiële naam van de machine met adres 134.184.65.2. Zulke namen zijn hiërarchisch gestructureerd (de machine ``tinf2'' behoort tot het domein ``vub.ac.be'' dat zelf weer een deeldomein is van ``ac.be'', hetwelk een deel is van het ``top'' domein ``be''. Men kan bvb. d.m.v. het ``nslookup'' programma nagaan wat het adres is dat hoort bij een naam (of omgekeerd).
Een machine op het net heeft een aantal poorten waarlangs een verbinding kan gemaakt worden met een poort van een andere machine. Sommige poorten worden, bij conventie, gebruikt voor bepaalde diensten. Bvb. wordt de poort nummer 80 veelal gebruikt door web servers. Wanneer bvb. mozilla (of konqueror, of netscape) vanop de machine 134.184.65.2 (tinf2) een verbinding wenst te maken naar de webserver op elvas.vub.ac.be (adres 134.18.65.31), dan wordt er een verbinding geopend tussen een poort, bvb 8026, op 134.184.65.2 en poort 80 op 134.18.65.31. D.m.v. het tcp protocol kunnen dan data uitgewisseld worden tussen de toepassingen aan beide kanten van de verbinding.
Voor het netwerk aspect kan gebruik gemaakt worden van het dvnet pakket dat o.a. een klasse Socket (voor clients) en SocketServer (voor servers) definieert. Omdat Socket afgeleid is van iostream is het sturen en ontvangen van gegevens via een netwerkverbinding heel makkelijk.
De map demo bevat een volledig uitgewerkt voorbeeld van een ``echo server'', dit is een server die elke lijn gestuurd door een client terugstuurt, na de tekst te hebben omgezet naar hoofdletters.
Omdat een typische server toepassing verschillende sessies/clients tegelijkertijd moet kunnen behandelen is het aangewezen om deze parallelle activiteiten te implementeren via verschillende ``threads''.
Voor deze toepassing volstaat het een thread te beschouwen als een proces dat zijn address space deelt met een ander proces (dit is trouwens min of meer de huidige implementatie van threads in linux). De uitvoering van een thread wordt verder geregeld zoals voor een proces; een multi-threaded programma kan dus verschillende activiteiten gelijktijdig uitvoeren. Omdat threads dezelfde address space delen is er natuurlijk een probleem om gemeenschappelijke data structuren te beschermen tegen gelijktijdige toegang. Een simpele oplossing gebruikt daarvoor zgn. ``monitors'' , dat zijn stukken code die slechts door één thread tegelijk kunnen uitgevoerd worden.
Voor ``threads'' en ``monitors'' zijn klassen beschikbaar in de dvthread bibliotheek (Java ondersteunt gelijkaardige klassen). De documentatie voor dvthread bevat ook een programma dat het gebruik van threads en monitors illustreert om concurrente toegang tot een gedeelde buffer te regelen voor verschillende ``reader'' en ``writer'' threads.
Meer info over threads en monitors is te vinden in deze nota's
Indien een programma een onbekend aantal threads dient op te starten is het nuttig om de nieuwe (sinds versie 0.4.5) constructor functie van Dv::Thread::Thread te gebruiken: indien met de constructor de bool parameter true wordt meegegeven, dan zorgt de dvthread bibliotheek ervoor dat het nieuw aangemaakte Dv::Thread::Thread object automatisch wordt deleted wanneer de corresponderende thread klaar is. Indien geen verdere informatie over de exit status van een thread moet opgevraagd worden, dan spaart het gebruik van deze optie een extra ``manager'' thread klasse uit die anders nodig zou zijn om andere threads te vernietigen, eens ze klaar zijn.
In het onderstaand voorbeeld wordt een klasse Session afgeleid van Dv::Thread::Thread zodanig dat elk Session object op de hierboven beschreven manier vernietigd wordt.
Voorbeeld 1. Een thread klasse afgeleid van Dv::Thread::Thread
class Session: public Dv::Thread::Thread { public: /** Een Session kan alleen met deze "factory" functie gemaakt * worden. Op die manier wordt vermeden dat per abuus * een Session op de stack wordt gemaakt, wat desastreuze * gevolgen zou hebben. */ static Session* make(..) { return new Session(..); } /** Destructor. */ virtual ~Session(..) { .. } .. private: /** De echte constructor is private, zie hoger. * Het meegeven van de optionele parameter "true" aan de * Dv::Thread::Thread constructor zorgt ervoor dat het * dvthread pakket zelf een delete zal uitvoeren eens * de aangemaakte Thread klaar is. */ Session(..): Dv::Thread::Thread(true) { .. } .. };
Een typische server main loop ziet er dan uit zoals in de onderstaande code.
while (true) { .. // Accept a new connection. .. (Session::make(..))->start(); // Launch new session thread. .. }
Schrijf[1] een eenvoudig webserver programma shttpd.
Het starten van de server gebeurt d.m.v. het volgende bevel.
shttpd configuration-file
waarbij de inhoud van het configuratiebestand een aantal parameters vastlegt, zoals getoond in het voorbeeld.
Voorbeeld 2. Voorbeeld shttpd configuratiebestand
# sample shttpd configuration file # documentroot: map waaronder bestanden opgezocht worden documentroot=/home/anne/htdocs # portnr: poort waarop de server luistert portnr=9999 # logfile: where log messages are written to logfile=/home/anne/shttpd.log # typesfile typesfile=/home/anne/shttpd.types
Een lijn in het configuratiebestand is dus ofwel een commentaarlijn, die begint met het teken '#', ofwel een definitie van de vorm naam=waarde waarbij naam en waarde één van de betekenissen uit de onderstaande tabel hebben.
Tabel 1. Configuratie-elementen
Naam | Waarde |
---|---|
port | nummer van de poort gebruikt door de server |
logfile | name van het bestand voor logboodschappen |
documentroot | absoluut pad naar een map waaronder de documenten die kunnen aangeboden worden zich bevinden |
typesfile | absoluut pad naar een bestand dat een suffix van een bestandsnaam associeert met een ``Content-Type''. |
Het opstarten resulteert in een daemon proces dat als webserver functioneert. Het programma kan enkel gestopt worden dmv het ``kill'' bevel.
Voor elk verzoek wordt precies één lijn aan de logfile toegevoegd. Zo'n lijn heeft een formaat zoals hierna geïllustreerd.
igwe.vub.ac.be - - [12/Feb/2000:13:18:49 +0100] "GET /images/openssl_ics.gif HTTP/1.0" 200 2063 134.184.65.2 - - [01/Nov/2000:15:42:44 +0100] "GET /ssl/kiesoos.cgi?rolnr=58769&stjcode=5L10021 HTTP/1.0" 302 300
Een lijn bestaat dus uit een aantal velden gescheiden door spaties. De betekenis van de velden is als volgt:
Het verzoek zelf, omringd door accenten ("). Dit verzoek bestaat zelf weer uit een aantal delen, gescheiden door spaties:
make clean rm -f shttpd *.o make all
De uiterste indiendatum is 27/8/2004, 23:59. Indienen gebeurt door me een e-mail bericht te sturen met een tarbal shttp.tar als aanhangsel. Een nette afdruk van een document dat uw ontwerp (hoe en waarom) kort beschrijft moet vóór die datum op het secretariaat van de vakgroep afgegeven worden. Later volgt dan een (individuele) mondeling verdediging. Zie ook de website.