Vývoj informačních systémů Námět na praktické cvičení Klient – Server (nepovinné)
Zadání Vytvoříme jednoduchý multithread HTTP server v jazyce Java Spustíme si ho na lokálním počítači A otestujeme ho Zdrojový kód je v cles/Networking/Webserver/WebServerco de.html cles/Networking/Webserver/WebServerco de.html cles/Networking/Webserver/WebServerco de.html
Hlavní myšlenky (1) Hlavní thread inicializuje server a spustí řadu pracovních threadů, které budou obsluhovat klientská spojení Pracovní thread čeká v klidovém stavu (idle), dokud se nepřipojí klient Hlavní thread přijme spojení od klienta, předá spojení pracovnímu threadu a čeká na dalšího klienta.
Hlavní myšlenky (2) V Javě je inicializace threadu spojena s řadou činností, a tedy pomalá. Proto thready nainicializujeme jen jednou, na začátku. Protože pracovní thready jsou vesměs v klidovém stavu Object.wait(), nepotřebují moc výkonu procesoru
Properties Vlastnosti HTTP serveru se nastaví v souboru:
Komentáře (1) WebServer.loadProps() (řádky 48-93) Tato metoda načte vlastnosti serveru ze souboru www-server.properties, který musí být v podadresáři lib umístěném v JAVA_HOME (=adresář, ve kterém je na vašem počítači interpreter Java)
Komentáře (2) root root je adresář, ve kterém HTTP server bude hledat soubory. Jinými slovy, root se připojí před jakoukoliv cestu k souboru, kterou zadá klient
Komentář (3) workers říká serveru, kolik pracovních threadů se má vytvořit při inicializaci. Současně to také znamená, kolik klientů může HTTP server obsluhovat současně.
Komentář (4) timeout udává počet milisekund, které má pracovní thread čekat při čtení z klientského spojení. Potom thread vygeneruje timeout a spojení ukončí. Kdyby to tak nebylo, klient by mohl server zablokovat tím, že by nekonečně dlouho otálel s příkazem
Komentář (5) log je to název souboru, do kterého se má ukládat protokol (log) práce serveru. Když není zadáno žádné jméno, protokol se vypisuje na standardní výstup.
Komentář (6) WebServer.main() zde se server inicializuje. Načte properties a vytvoří pole pracovních threadů. Poté naváže ServerSocket na lokální port našeho HTTP serveru a spustí smyčku. V ní přijímá klientská spojení a předává je pracovním threadům.
Komentář (7) třída Worker (řádky ) Třída implementuje java.lang.Runnable Běží uvnitř pracovního threadu, kde vykonává konkrétní práci se soubory. Protože v Java alokace paměti může být časově náročná, buffer (byte array) alokujeme jen jednou v konstruktoru a používáme ho opakovaně
Komentář (8) Worker.run() Pracovní thready stráví většinu života čekáním na řádce 162 ve wail(). Když přijde klientské spojení, pracovní thread se probudí a obslouží ho
Komentář (9) Worker.setSocket() (řádky ) Když přijde spojení od klienta, hlavní thread najde neaktivní pracovní thread (řádky ) a zavolá setSocket() na Worker, čímž se na Worker vyvolá notify() Tím se pracovní thread probudí z wait() setSocket() musí být synchronized, aby fungovala notify().
Komentář (10) Worker.handleClient() (řádky ) Smyčka, která načte 1. řádek klientova HTTP dotazu. Obvykle má formu GET /foo/bar/baz.html HTTP/1.0 Java nemá goto, a tak se jméno souboru musí analyzovat trochu složitěji. Jsou tam na to dvě smyčky (pokrač…)
…pokračování Vnější smyčka while() je čtecí a vnitřní smyčka for() prochází jednotlivé byty a hledá znaky konce řádku. break je sice ve vnitřní smyčce, ale fakticky způsobí i opuštění vnější smyčky.
Komentář (11) třída Worker (řádky , ) Je důležité, aby se sockety i soubory vždycky správně uzavřely (i při chybách)
Komentář (12) Worker.handleClient() (řádek 303) IP adresu klienta a který soubor požaduje, zapíšeme do logu. IP získáme voláním s.getInetAddress().getHostAddress(), kdyby se zde volala …getHostName(), bylo by to pomalé (inverzní DNS look-up) Kdo potřebuje HostName, může si to později vyhledat.
Ladění Pro ladění je skvělý HTTP header viewer, protože umí sledovat skutečnou síťovou komunikaci: – – viewer.html?noprint=true
The End