Vorgurakendused 2 prax 1 2016: erinevus redaktsioonide vahel

Allikas: Lambda
Mine navigeerimisribale Mine otsikasti
PriitJ (arutelu | kaastöö)
Resümee puudub
PriitJ (arutelu | kaastöö)
 
(ei näidata sama kasutaja 16 vahepealset redaktsiooni)
1. rida: 1. rida:
Ülesandeks on implementeerida lihtne P2P protokoll (rakendus selgub lähiajal)
Ülesandeks on implementeerida lihtne P2P protokoll anonüümseks HTTP päringute tegemiseks.
* realiseeritud HTTP protokolli peale (vaja implementeerida ka HTTP server ja klient)
* realiseeritud HTTP protokolli peale (vaja implementeerida ka HTTP server ja klient)
* hakkab tööle virtuaalses võrgus (https://rangeforce.com/)
* hakkab tööle virtuaalses võrgus (tehtud kohaliku startupi https://rangeforce.com/ poolt)
* eesmärk kõigi rakendused omavahel suhtlema ja ühise võrguna tegutsema panna
* eesmärk kõigi rakendused omavahel suhtlema ja ühise võrguna tegutsema panna


18. rida: 18. rida:
# Käsurea git klient (GIT bash Windowsi all või git käsk Linuxi/Maci all). Sel puhul järgi Gitlabi/Githubi/Bitbucketi juhiseid repo kohalikku arvutisse kloonimiseks ning selle initsialiseerimiseks.
# Käsurea git klient (GIT bash Windowsi all või git käsk Linuxi/Maci all). Sel puhul järgi Gitlabi/Githubi/Bitbucketi juhiseid repo kohalikku arvutisse kloonimiseks ning selle initsialiseerimiseks.


Virtuaallaborisse sisse logimine
=== Virtuaallabor ===


User/pass: student/student
Logi sisse oma TTÜ ''uni-id''-ga: https://itee.cs.ttu.ee/


Repo kloonimine virtuaalmasinasse
(kasutajad, kelle nimes on '-' märk, peavad õppejõu käest eraldi ligipääsutokeni küsima).
 
Mine "Labs" sakile. Labori "ITV0120 P2P" kirjeldus on lahti, juhul kui pole siis vajuta üleval vasakul menüüriba all noolekesele ja vali sellise nimega labor. Näed ülesande kirjeldust, virtuaalmasinate nimekirja ja nupurida all. Nuppude tähendus:
* Start all - pane virtuaalmasinad käima
* Stop all - pane virtuaalmasinad seisma. Tee seda, kui ei testi või ei arenda, aga ära unusta poolikut tööd salvestada.
* Restart lab - alusta laboriga algusest, kõik muudatused (k.a. ise installitud soft) kustuvad.
* End lab - kustutab labori ära.
 
Töötamiseks on desktop masin. Sinna saab sisse välise RDP kliendiga (kliki oma opsüsteemile vastavale nupule, et juhiseid näha) või lihtsalt vajutades nupule "open in browser". Desktop masinas on kasutaja "student" parooliga "student".
 
Oma repo kloonimiseks virtuaallaborisse ava terminal ja tee näiteks:
 
  git clone https://gitlab.com/priitj/test3.git
 
[[Vorgurakendused 2 prax 1 2016 abiks | Veel giti ja muid kasulikke käske]]


== HTTP server/klient ==
== HTTP server/klient ==


HTTP baasil töötav protokoll näeb välja umbes järgmine (kasutame ainult GET päringuid):
HTTP baasil töötav protokoll näeb välja umbes järgmine:


   http://1.2.3.4/request?param1=val1&param2=val2
   GET http://1.2.3.4/request?param1=val1&param2=val2
   http://1.2.3.5/response?param1=val1&param3=val3
   POST http://1.2.3.5/response?param1=val1&param3=val3


jne. Seega tuleb meil teha:
jne. Seega tuleb meil teha:


# HTTP server, mis suudaks vastu võtta GET päringut ning parseerida pathi ja parameetrid (query stringi). Meid huvitab ka IP, kust päring tuli, see tuleb edaspidi kasutamiseks meelde jätta.
# HTTP server, mis suudaks vastu võtta GET ja POST päringut ning parseerida pathi ja parameetrid (query stringi). Meid huvitab ka IP, kust päring tuli, see tuleb edaspidi kasutamiseks meelde jätta. POST päringu puhul peab lugema päringu "keha" (body).
# Selle peale peaks serveris käivituma mingi funktsioon. Selle võime jätta hetkel tühjaks
# Selle peale peaks serveris käivituma mingi funktsioon. Selle võime jätta hetkel tühjaks
# Lõpuks saadame vastuse samuti GET päringuga. Seega vaja selleks HTTP klienti.
# Lõpuks saadame vastuse samuti HTTP päringuga. Seega vaja selleks HTTP klienti.


Server tuleb realiseerida ise, kasutades võrgust leitavaid näiteid mikro-http-serveri jaoks (tüüpiliselt paar lehekülge koodi). Selliseid näitekoode võib täiesti otse kasutada.
Server tuleb realiseerida ise, kasutades võrgust leitavaid näiteid mikro-http-serveri jaoks (tüüpiliselt paar lehekülge koodi). Selliseid näitekoode võib täiesti otse kasutada.


C jaoks on sobiv mikroserver näiteks [http://www.lambda.ee/images/8/89/Itsissejuhatus_tiny.zip tiny], java jaoks sobib alustuseks [http://stackoverflow.com/questions/3732109/simple-http-server-in-java-using-only-java-se-api sisseehitatud HTTP server]. Socketi tasemel alternatiivid on
C jaoks on sobiv mikroserver näiteks [http://tinyhttpd.cvs.sourceforge.net/viewvc/tinyhttpd/tinyhttpd/httpd.c?revision=1.4&view=markup tiny], java jaoks sobib alustuseks [http://stackoverflow.com/questions/3732109/simple-http-server-in-java-using-only-java-se-api sisseehitatud HTTP server]. Socketi tasemel alternatiividest
on [http://www.java2s.com/Code/Java/Tiny-Application/HttpServer.htm see server] väga hea väike näide, aga selgitava tekstita,
on [http://www.java2s.com/Code/Java/Tiny-Application/HttpServer.htm see server] väga hea väike näide, aga selgitava tekstita,
ning selgitavate tekstidega servereid leiad mh [http://onjava.com/pub/a/onjava/2003/04/23/java_webserver.html siit] ja
ning selgitavate tekstidega servereid leiad mh [http://onjava.com/pub/a/onjava/2003/04/23/java_webserver.html siit] ja
[http://fragments.turtlemeat.com/javawebserver.php siit].Loe java socketitest põhjalikumalt [http://download.oracle.com/javase/tutorial/networking/sockets/ siit]. Pythoni serverinäite [http://muharem.wordpress.com/2007/05/29/roll-your-own-server-in-50-lines-of-code/ saad siit]; [https://daanlenaerts.com/blog/2015/06/03/create-a-simple-http-server-with-python-3/ lühem ja uuem]. Http kohta võib lugeda [http://www.jmarshall.com/easy/http/ näiteks siit].
[http://fragments.turtlemeat.com/javawebserver.php siit].Loe java socketitest põhjalikumalt [http://download.oracle.com/javase/tutorial/networking/sockets/ siit]. Pythoni serverinäite [http://muharem.wordpress.com/2007/05/29/roll-your-own-server-in-50-lines-of-code/ saad siit]; [https://daanlenaerts.com/blog/2015/06/03/create-a-simple-http-server-with-python-3/ lühem ja uuem]. Http kohta võib lugeda [http://www.jmarshall.com/easy/http/ näiteks siit].


== Rakenduse ideed ==
== Rakendus: anonümiseeriv võrk ==
 
Eesmärgiks on ehitada anonümiseeriv võrk nagu [https://www.torproject.org/ Tor]. Täpsemalt on eeskujuks praeguseks mitteaktiivne anonüümne failijagamise võrk [http://mute-net.sourceforge.net/ MUTE Network]. Sealt võetud ideid kasutades teeme võrgu, kus saab anonüümselt veebist faile (html vms) alla laadida.
 
Meie võrgus teab iga võrgusõlm (node) näiteks kolme naabrit. Kui sõlm A tahab alla laadida URL-i http://google.ee, saadab ta päringu kõigile oma naabritele. Need omakorda saadavad päringu oma naabritele jne. Päringul on kaasas salajane identifikaator - ainult A teab, et see identifikaator seostub temaga. Lõpuks jõutakse võrgusõlmeni B, kes otsustab, et laadib ise URL-i sisu alla. B ei tea kes URL-i sisu soovis, aga saadab vastuse suunas, kust ta päringu sai. Samal viisil liigub vastus mööda võrku tagasi, kuni jõuab A-ni, kes tunneb ära oma salajase identifikaatori.


* masspäringute hajutamine
Võrku liituda ja sealt lahkuda võib suvalisel ajal. Seetõttu tuleb liitudes ja edasi perioodiliselt värsket naabrite nimekirja küsida, selleks paigutatakse samasse võrgu eraldi kataloogiserver.
* content distribution (streaming)
* maksed
* maatriksite korrutamine
* anonümiseeriv võrk


== Protokoll ==
== Protokoll ==


'''Päringu saamise kinnitus'''. Peale iga HTTP requesti saamist vastab P2P node tekstiga <code>"OK"</code> juhul kui ei olnud viga ning tekstiga <code>"Error: xxxxxxxxxxx"</code> kui oli viga (''xxxxxxxxxxx'' tähistab vabas vormis vea kirjeldust ning selle võib ka ära jätta).
'''Port'''. Vaikimisi on eeldatud, et võrgusõlmed kasutavad sõnumite vastuvõtmiseks porti 1215. Kasuta seda, kui suhtled teiste üliõpilaste programmidega ja kataloogiserveriga virtuaallaboris. Iseseisvaks või kohalikuks testimiseks võib kasutada ka muid porte.
 
'''Päringu saamise kinnitus'''. Peale iga HTTP päringu saamist vastab võrgusõlm tekstiga <code>"OK"</code> juhul kui ei olnud viga ning tekstiga <code>"Error: xxxxxxxxxxx"</code> kui oli viga (''xxxxxxxxxxx'' tähistab vabas vormis vea kirjeldust ning selle võib ka ära jätta). Vastuse saatmine on kohustuslik, isegi kui võrgusõlm päringuga tulnud sõnumit ignoreerib. Korrektse sõnumi puhul peab vastuse HTTP staatus olema 200, muul juhul on lubatud ka HTTP veakoodide esinemine.
 
'''Naabrite nimekiri'''. Iga minuti tagant tuleb naabrite nimekirja kataloogiserverist uuendada (vt allpool).
 
=== URL-i (faili) alla laadimise päring ===
 
{| class="wikitable"
|-
|nimi (path)
|/download
|-
|parameetrid
|?id=''xxxxxxxx''&url=''yyyyyyy''
|-
|tüüp
|HTTP GET
|-
|body
|
|}
 
''xxxxxxxx'' on selle sõnumi jaoks genereeritud juhuslik number. Kui sama võrgusõlm näeb hiljem sama id-ga <code>file</code> sõnumit, siis see sisaldab soovitud vastust. ''yyyyyyy'' on täispikk URL, mis peab olema [https://en.wikipedia.org/wiki/Percent-encoding turvaliselt kodeeritud], [https://docs.python.org/3.5/library/urllib.parse.html#url-quoting Pythoni lahendus].
 
Näide: http://1.2.3.4:1215/download?id=7652354352&url=http%3A//google.ee/%3Fs%3Dbla%26lang%3Den
 
Käsitlemise reeglid:
# Kui sõlm algatab ise selle päringu, peab ta meelde jätma <code>id</code>, et hiljem vastust ära tunda
# Päringu algatav võrgusõlm saadab sõnumi kõigile hetkel teadaolevatele naabritele
# Esimest korda selle sõnumi vastu võtmisel otsustab võrgusõlm, kas faili alla laadida (tõenäosus ''x%'', konfitav)
## Kui faili alla ei laadita, saadab võrgusõlm sõnumi edasi kõigile oma naabritele, v.a juhul kui naabri IP langeb kokku sõnumi edastanud sõlme IP-ga
## Kui fail alla laaditakse, siis algatatakse <code>file</code> tüüpi sõnum (vt. allpool)
## Mõlemal juhul tuleb meelde jätta sõnumi <code>id</code> ja edastanud võrgusõlme IP
# Teist korda sama (või enda algatatud) <code>id</code>-ga sõnumi vastu võtmise korral seda ignoreeritakse
# Päringu algatanud sõlm peab arvestama võimalusega, et võrgu ebastabiilse iseloomu tõttu ei ole vastuse saabumine garanteeritud
 
=== Faili sisu tagastamine ===
 
{| class="wikitable"
|-
|nimi (path)
|/file
|-
|parameetrid
|?id=''xxxxxxxx''
|-
|tüüp
|HTTP POST
|-
|body
|{"status":yyy, "mime-type":"zzzzzzzz", "content":"..."}
|}
 
''xxxxxxxx'' on sama, mis <code>download</code> sõnumis, mille saamise tõttu fail alla laaditi. HTTP päringu kehas on JSON formaadis objekt, mis sisaldab ''base64'' kodeeringus faili ja selle metadatat. ''yyy'' on faili allalaadimisel saadud HTTP staatus. ''zzzzzzzz'' on faili sisu MIME tüüp (peale dekodeerimist). "content" väljal on RFC-3548 ühilduvas ''base64'' kodeeringus ([https://docs.python.org/3/library/base64.html Pythoni tugi]) faili sisu.
 
URI näide: http://5.6.7.8:1215/file?id=7652354352
 
Keha näide 1:
 
  {"status":200, "mime-type":"text/html", "content":
  "PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBYSFRNTC..."}
 
Keha näide 2 (viga):
 
  {"status":404}
 
Käsitlemise reeglid:
# Päringu algatav võrgusõlm saadab sõnumi naabrile, kellelt sama <code>id</code>-ga <code>download</code> sõnumi vastu võttis
# Kui eelmine samm ebaõnnestus, saadetakse sõnum kõigile naabritele
# Esimest korda selle sõnumi vastu võtmisel otsustab võrgusõlm, kas fail oli tema enda soovitud (<code>id</code> parameeter)
## Kui ei olnud, saadab võrgusõlm sõnumi edasi naabrile, kellelt saabus sama <code>id</code>-ga <code>download</code> päring
## Kui eelmine samm ebaõnnestus (või sellist naabrit ei teata), saadetakse sõnum edasi kõigile naabritele, v.a. juhul kui naabri IP langeb kokku käsitletava <code>file</code> sõnumi saatja IP-ga
## Kui fail oli sõlme enda soovitud, parseeritakse päringu kehast staatus ja olemasolul faili sisu.
# Teist korda sama (või enda algatatud) <code>id</code>-ga sõnumi vastu võtmise korral seda ignoreeritakse
 
=== Millal faili alla laadida? ===
 
Oletame, et võrgus on 10 arvutit. Kui allalaadimispäring laiali saadetakse, peaks üks neist hakkama faili alla laadima, ülejäänud 9-l pole seda vaja teha. Kuidas aga otsustada, kelle töö on fail alla laadida? Korrektne viis seda teha oleks [https://en.wikipedia.org/wiki/Distributed_hash_table DHT] abil, mis aga mitmekordistaks protokolli keerukust. Kui me aga loobume korrektsusest lihtsuse huvides, saab asja teha ka täiesti suhtlusvabalt.
 
Igal võrgusõlmel on oma "laiskuse mõõt", näiteks antud juhul number 0.9. Kui võrgusõlm näeb päringut, mille peale tuleks algatada faili alla laadimine, leiab ta juhusliku numbri vahemikus 0 kuni 1. Kui see on suurem kui tema laiskus, siis tuleb hakata faili alla laadima. Kui aga laiskus on suurem, siis saadetakse sõnum edasi teistele. Antud näite puhul on kõige tõenäolisem, et üks võrgusõlm hakkab faili alla laadima, ehkki võib ka juhtuda, et neid on mitu või mitte ühtegi.
 
== Kataloogiserver ==
 
Kataloogiserveriga suhtlemine toimub lihtsa klient-serveri mudeli abil, seal pole P2P protokolli tarvis. Naabrite küsimine:
 
  http://192.168.3.11:1215/getpeers
 
Vastus:
 
  [ "1.2.3.4:1215", "5.6.7.8:1215", "1.2.3.6:1215" ]
 
Vastus on JSON formaadis. Naabreid võib olla ka rohkem või vähem kui 3 (näiteks juhul, kui keegi teine pole võrguga liitunud).
 
== Soovitused ==
 
'''Konfiguratsioon'''. Formaat pole oluline, aga mõtekas on järgmised parameetrid konfigureeritavaks teha. Pordi võib teha ka käsureaparameetriks:
 
  ; lokaalse testimise korral vähenda, suures võrgus suurenda
  laziness = 0.5
  ; kataloogiteenus, siia võid panna ka staatilise tekstifaili URL-i
  directory = http://192.168.3.249:1215/getpeers
  ; lokaalseks mitme instantsiga testimiseks
  port = 1215
 
'''Naabrite tabel'''. Täidetakse kataloogiserverit kasutades.
 
{| class="wikitable"
!nr
!ip
!port
!elus
|-
|1
|1.2.3.4
|1215
|Y
|-
|2
|5.6.7.8
|1215
|Y
|-
|3
|1.2.3.6
|1215
|N
|-
|4
|
|
|
|}
 
Väli <code>elus</code> võimaldab meelde jätta, kui naaber võrgust ära kaob. Seda saab asendada ka ajatempliga, aga jah/ei lipu käsitlemine on lihtsam.
 
'''Minu päringute tabel'''. Kuna igal päringul on uus <code>id</code>, tuleb mitme päringu tegemisel ajalugu meelde jätta.
 
{| class="wikitable"
!nr
!id
!url
!ajatempel
|-
|1
|7652354352
|http://google.ee/?s=bla&lang=en
|Sat Sep 17 02:16:57 2016
|-
|2
|
|
|
|}
 
Väli <code>url</code> on kasulik näiteks veateadete edastamiseks. <code>ajatempel</code> abil saab tuvastada, kui kaua päring on vastust oodanud ning vajadusel päringut korrata - sel juhul tuleb kindlasti uus identifikaator genereerida - või anda veateade.
 
'''Marsruutimistabel'''. Kui ülejäänud tabelid on "maitse küsimus", siis protokollis ette nähtud sõnumite käsitlusreeglite järgmiseks on järgnev marsruutimistabeli formaat oluliseks lihtsustavaks abivahendiks.
 
{| class="wikitable"
!nr
!id
!download ip
!file ip
|-
|1
|7652354352
|1.2.3.4
|
|-
|2
|7657856788
|
|5.6.7.8
|-
|3
|9845345233
|1.2.3.6
|5.6.7.8
|-
|4
|
|
|
|}
 
<code>download ip</code> on naabri IP, kes saatis meile vastava identifikaatoriga <code>download</code> sõnumi. Juhul kui näeme sama identifikaatoriga <code>file</code> sõnumit, tuleks meil just <code>download ip</code> aadressile see edastada. Mõeldav on ka juhtum, kus meil tuleb sisse <code>file</code> sõnum, millele vastavat <code>download</code> sõnumit me ei ole näinud. See tuleb aga ikkagi marsruutimistabelisse registreerida, et korduvat sõnumite laialisaatmist vältida (rida 2). <code>file</code> sõnumi saatja IP läheb väljale <code>file ip</code>. Juhul kui mõlemad sõnumid on nähtud, siis on mõlemad IP-d täidetud (rida 3) ning igasugusel edasisel kokkupuutel antud identifikaatoriga pole enam tarvis reageerida.
 
Seda tabelit saab täiendada ka ajatempliga, et vanemaid kirjeid kustutama hakata. Väikeste testimismahtude juures pole see veel vajalik.
 
'''Juhtimine''' Et testida, on minimaalselt vaja rakendusele ka alla laaditavaid URL-e ette sööta. Selleks on mõeldavad järgmised viisid:
* lähtekoodi sisse kirjutatud, lihtne teha aga raske hallata
* loetakse tekstifailist rakenduse käivitamisel
* antakse rakendusele käsurea argumendiks
* reaalajas üle HTTP (võimaldab näiteks AJAX-iga veebiliides lisada)
* reaalajas käsurealiidese (CLI) abil
* ...
 
Testimiseks on soovitatav esialgu lihtsam variant võtta ning hiljem kui rakendus juba suuremalt osalt töötab, leida viis, mis võimaldab paindlikumalt ja massilisemalt testida.


<b>Praktikumi kirjeldus täieneb jooksvalt semestri käigus</b>
<b>Praktikumi kirjeldus täieneb jooksvalt semestri käigus</b>

Viimane redaktsioon: 29. september 2016, kell 07:02

Ülesandeks on implementeerida lihtne P2P protokoll anonüümseks HTTP päringute tegemiseks.

  • realiseeritud HTTP protokolli peale (vaja implementeerida ka HTTP server ja klient)
  • hakkab tööle virtuaalses võrgus (tehtud kohaliku startupi https://rangeforce.com/ poolt)
  • eesmärk kõigi rakendused omavahel suhtlema ja ühise võrguna tegutsema panna

Ettevalmistus

Vali arenduseks töövahend: virtuaallaboris on olemas Java (+maven) ning Python 3 tugi. Muud keeled (Haskell, C, Javascript, C#) eeldavad, et tudeng saab ise arenduskeskkonna tööle. Seda on kasulik kohe alguses testida. Virtuaalmasinas jookseb Ubuntu desktop 16.04.

Tee avalikku git SCM teenusesse uus repo. Sobivad teenused on http://gitlab.com, http://github.com, http://bitbucket.com .

Leia tehtud repo URI. Näiteks: git@gitlab.com:priitj/test3.git (SSH), https://gitlab.com/priitj/test3.git (HTTPS).

Üle SSH protokolli reposse pöördumiseks on vaja täiendavalt teha SSH võti. Selleks vaata juhendeid, näit. Githubi puhul https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ ; https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/ (need juhendid sisaldavad ka konfi Windowsi/Linuxi/Maci git kliendi jaoks).

Töö käigus repo kasutamiseks on kaks alternatiivi:

  1. IDE-sse integreeritud giti klient. IntelliJ/PyCharm puhul tee uus projekt selliselt, et vali VCS->Checkout from Version Control->Git, pane URI (SSH või HTTPS oma) ning uus kataloog. Siis "Clone" ning edaspidi on projekti töökataloog juba seotud eelnevalt tehtud repoga.
  2. Käsurea git klient (GIT bash Windowsi all või git käsk Linuxi/Maci all). Sel puhul järgi Gitlabi/Githubi/Bitbucketi juhiseid repo kohalikku arvutisse kloonimiseks ning selle initsialiseerimiseks.

Virtuaallabor

Logi sisse oma TTÜ uni-id-ga: https://itee.cs.ttu.ee/

(kasutajad, kelle nimes on '-' märk, peavad õppejõu käest eraldi ligipääsutokeni küsima).

Mine "Labs" sakile. Labori "ITV0120 P2P" kirjeldus on lahti, juhul kui pole siis vajuta üleval vasakul menüüriba all noolekesele ja vali sellise nimega labor. Näed ülesande kirjeldust, virtuaalmasinate nimekirja ja nupurida all. Nuppude tähendus:

  • Start all - pane virtuaalmasinad käima
  • Stop all - pane virtuaalmasinad seisma. Tee seda, kui ei testi või ei arenda, aga ära unusta poolikut tööd salvestada.
  • Restart lab - alusta laboriga algusest, kõik muudatused (k.a. ise installitud soft) kustuvad.
  • End lab - kustutab labori ära.

Töötamiseks on desktop masin. Sinna saab sisse välise RDP kliendiga (kliki oma opsüsteemile vastavale nupule, et juhiseid näha) või lihtsalt vajutades nupule "open in browser". Desktop masinas on kasutaja "student" parooliga "student".

Oma repo kloonimiseks virtuaallaborisse ava terminal ja tee näiteks:

 git clone https://gitlab.com/priitj/test3.git

Veel giti ja muid kasulikke käske

HTTP server/klient

HTTP baasil töötav protokoll näeb välja umbes järgmine:

 GET http://1.2.3.4/request?param1=val1&param2=val2
 POST http://1.2.3.5/response?param1=val1&param3=val3

jne. Seega tuleb meil teha:

  1. HTTP server, mis suudaks vastu võtta GET ja POST päringut ning parseerida pathi ja parameetrid (query stringi). Meid huvitab ka IP, kust päring tuli, see tuleb edaspidi kasutamiseks meelde jätta. POST päringu puhul peab lugema päringu "keha" (body).
  2. Selle peale peaks serveris käivituma mingi funktsioon. Selle võime jätta hetkel tühjaks
  3. Lõpuks saadame vastuse samuti HTTP päringuga. Seega vaja selleks HTTP klienti.

Server tuleb realiseerida ise, kasutades võrgust leitavaid näiteid mikro-http-serveri jaoks (tüüpiliselt paar lehekülge koodi). Selliseid näitekoode võib täiesti otse kasutada.

C jaoks on sobiv mikroserver näiteks tiny, java jaoks sobib alustuseks sisseehitatud HTTP server. Socketi tasemel alternatiividest on see server väga hea väike näide, aga selgitava tekstita, ning selgitavate tekstidega servereid leiad mh siit ja siit.Loe java socketitest põhjalikumalt siit. Pythoni serverinäite saad siit; lühem ja uuem. Http kohta võib lugeda näiteks siit.

Rakendus: anonümiseeriv võrk

Eesmärgiks on ehitada anonümiseeriv võrk nagu Tor. Täpsemalt on eeskujuks praeguseks mitteaktiivne anonüümne failijagamise võrk MUTE Network. Sealt võetud ideid kasutades teeme võrgu, kus saab anonüümselt veebist faile (html vms) alla laadida.

Meie võrgus teab iga võrgusõlm (node) näiteks kolme naabrit. Kui sõlm A tahab alla laadida URL-i http://google.ee, saadab ta päringu kõigile oma naabritele. Need omakorda saadavad päringu oma naabritele jne. Päringul on kaasas salajane identifikaator - ainult A teab, et see identifikaator seostub temaga. Lõpuks jõutakse võrgusõlmeni B, kes otsustab, et laadib ise URL-i sisu alla. B ei tea kes URL-i sisu soovis, aga saadab vastuse suunas, kust ta päringu sai. Samal viisil liigub vastus mööda võrku tagasi, kuni jõuab A-ni, kes tunneb ära oma salajase identifikaatori.

Võrku liituda ja sealt lahkuda võib suvalisel ajal. Seetõttu tuleb liitudes ja edasi perioodiliselt värsket naabrite nimekirja küsida, selleks paigutatakse samasse võrgu eraldi kataloogiserver.

Protokoll

Port. Vaikimisi on eeldatud, et võrgusõlmed kasutavad sõnumite vastuvõtmiseks porti 1215. Kasuta seda, kui suhtled teiste üliõpilaste programmidega ja kataloogiserveriga virtuaallaboris. Iseseisvaks või kohalikuks testimiseks võib kasutada ka muid porte.

Päringu saamise kinnitus. Peale iga HTTP päringu saamist vastab võrgusõlm tekstiga "OK" juhul kui ei olnud viga ning tekstiga "Error: xxxxxxxxxxx" kui oli viga (xxxxxxxxxxx tähistab vabas vormis vea kirjeldust ning selle võib ka ära jätta). Vastuse saatmine on kohustuslik, isegi kui võrgusõlm päringuga tulnud sõnumit ignoreerib. Korrektse sõnumi puhul peab vastuse HTTP staatus olema 200, muul juhul on lubatud ka HTTP veakoodide esinemine.

Naabrite nimekiri. Iga minuti tagant tuleb naabrite nimekirja kataloogiserverist uuendada (vt allpool).

URL-i (faili) alla laadimise päring

nimi (path) /download
parameetrid ?id=xxxxxxxx&url=yyyyyyy
tüüp HTTP GET
body

xxxxxxxx on selle sõnumi jaoks genereeritud juhuslik number. Kui sama võrgusõlm näeb hiljem sama id-ga file sõnumit, siis see sisaldab soovitud vastust. yyyyyyy on täispikk URL, mis peab olema turvaliselt kodeeritud, Pythoni lahendus.

Näide: http://1.2.3.4:1215/download?id=7652354352&url=http%3A//google.ee/%3Fs%3Dbla%26lang%3Den

Käsitlemise reeglid:

  1. Kui sõlm algatab ise selle päringu, peab ta meelde jätma id, et hiljem vastust ära tunda
  2. Päringu algatav võrgusõlm saadab sõnumi kõigile hetkel teadaolevatele naabritele
  3. Esimest korda selle sõnumi vastu võtmisel otsustab võrgusõlm, kas faili alla laadida (tõenäosus x%, konfitav)
    1. Kui faili alla ei laadita, saadab võrgusõlm sõnumi edasi kõigile oma naabritele, v.a juhul kui naabri IP langeb kokku sõnumi edastanud sõlme IP-ga
    2. Kui fail alla laaditakse, siis algatatakse file tüüpi sõnum (vt. allpool)
    3. Mõlemal juhul tuleb meelde jätta sõnumi id ja edastanud võrgusõlme IP
  4. Teist korda sama (või enda algatatud) id-ga sõnumi vastu võtmise korral seda ignoreeritakse
  5. Päringu algatanud sõlm peab arvestama võimalusega, et võrgu ebastabiilse iseloomu tõttu ei ole vastuse saabumine garanteeritud

Faili sisu tagastamine

nimi (path) /file
parameetrid ?id=xxxxxxxx
tüüp HTTP POST
body {"status":yyy, "mime-type":"zzzzzzzz", "content":"..."}

xxxxxxxx on sama, mis download sõnumis, mille saamise tõttu fail alla laaditi. HTTP päringu kehas on JSON formaadis objekt, mis sisaldab base64 kodeeringus faili ja selle metadatat. yyy on faili allalaadimisel saadud HTTP staatus. zzzzzzzz on faili sisu MIME tüüp (peale dekodeerimist). "content" väljal on RFC-3548 ühilduvas base64 kodeeringus (Pythoni tugi) faili sisu.

URI näide: http://5.6.7.8:1215/file?id=7652354352

Keha näide 1:

 {"status":200, "mime-type":"text/html", "content":
 "PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBYSFRNTC..."}

Keha näide 2 (viga):

 {"status":404}

Käsitlemise reeglid:

  1. Päringu algatav võrgusõlm saadab sõnumi naabrile, kellelt sama id-ga download sõnumi vastu võttis
  2. Kui eelmine samm ebaõnnestus, saadetakse sõnum kõigile naabritele
  3. Esimest korda selle sõnumi vastu võtmisel otsustab võrgusõlm, kas fail oli tema enda soovitud (id parameeter)
    1. Kui ei olnud, saadab võrgusõlm sõnumi edasi naabrile, kellelt saabus sama id-ga download päring
    2. Kui eelmine samm ebaõnnestus (või sellist naabrit ei teata), saadetakse sõnum edasi kõigile naabritele, v.a. juhul kui naabri IP langeb kokku käsitletava file sõnumi saatja IP-ga
    3. Kui fail oli sõlme enda soovitud, parseeritakse päringu kehast staatus ja olemasolul faili sisu.
  4. Teist korda sama (või enda algatatud) id-ga sõnumi vastu võtmise korral seda ignoreeritakse

Millal faili alla laadida?

Oletame, et võrgus on 10 arvutit. Kui allalaadimispäring laiali saadetakse, peaks üks neist hakkama faili alla laadima, ülejäänud 9-l pole seda vaja teha. Kuidas aga otsustada, kelle töö on fail alla laadida? Korrektne viis seda teha oleks DHT abil, mis aga mitmekordistaks protokolli keerukust. Kui me aga loobume korrektsusest lihtsuse huvides, saab asja teha ka täiesti suhtlusvabalt.

Igal võrgusõlmel on oma "laiskuse mõõt", näiteks antud juhul number 0.9. Kui võrgusõlm näeb päringut, mille peale tuleks algatada faili alla laadimine, leiab ta juhusliku numbri vahemikus 0 kuni 1. Kui see on suurem kui tema laiskus, siis tuleb hakata faili alla laadima. Kui aga laiskus on suurem, siis saadetakse sõnum edasi teistele. Antud näite puhul on kõige tõenäolisem, et üks võrgusõlm hakkab faili alla laadima, ehkki võib ka juhtuda, et neid on mitu või mitte ühtegi.

Kataloogiserver

Kataloogiserveriga suhtlemine toimub lihtsa klient-serveri mudeli abil, seal pole P2P protokolli tarvis. Naabrite küsimine:

 http://192.168.3.11:1215/getpeers

Vastus:

 [ "1.2.3.4:1215", "5.6.7.8:1215", "1.2.3.6:1215" ]

Vastus on JSON formaadis. Naabreid võib olla ka rohkem või vähem kui 3 (näiteks juhul, kui keegi teine pole võrguga liitunud).

Soovitused

Konfiguratsioon. Formaat pole oluline, aga mõtekas on järgmised parameetrid konfigureeritavaks teha. Pordi võib teha ka käsureaparameetriks:

 ; lokaalse testimise korral vähenda, suures võrgus suurenda
 laziness = 0.5
 ; kataloogiteenus, siia võid panna ka staatilise tekstifaili URL-i
 directory = http://192.168.3.249:1215/getpeers
 ; lokaalseks mitme instantsiga testimiseks
 port = 1215

Naabrite tabel. Täidetakse kataloogiserverit kasutades.

nr ip port elus
1 1.2.3.4 1215 Y
2 5.6.7.8 1215 Y
3 1.2.3.6 1215 N
4

Väli elus võimaldab meelde jätta, kui naaber võrgust ära kaob. Seda saab asendada ka ajatempliga, aga jah/ei lipu käsitlemine on lihtsam.

Minu päringute tabel. Kuna igal päringul on uus id, tuleb mitme päringu tegemisel ajalugu meelde jätta.

nr id url ajatempel
1 7652354352 http://google.ee/?s=bla&lang=en Sat Sep 17 02:16:57 2016
2

Väli url on kasulik näiteks veateadete edastamiseks. ajatempel abil saab tuvastada, kui kaua päring on vastust oodanud ning vajadusel päringut korrata - sel juhul tuleb kindlasti uus identifikaator genereerida - või anda veateade.

Marsruutimistabel. Kui ülejäänud tabelid on "maitse küsimus", siis protokollis ette nähtud sõnumite käsitlusreeglite järgmiseks on järgnev marsruutimistabeli formaat oluliseks lihtsustavaks abivahendiks.

nr id download ip file ip
1 7652354352 1.2.3.4
2 7657856788 5.6.7.8
3 9845345233 1.2.3.6 5.6.7.8
4

download ip on naabri IP, kes saatis meile vastava identifikaatoriga download sõnumi. Juhul kui näeme sama identifikaatoriga file sõnumit, tuleks meil just download ip aadressile see edastada. Mõeldav on ka juhtum, kus meil tuleb sisse file sõnum, millele vastavat download sõnumit me ei ole näinud. See tuleb aga ikkagi marsruutimistabelisse registreerida, et korduvat sõnumite laialisaatmist vältida (rida 2). file sõnumi saatja IP läheb väljale file ip. Juhul kui mõlemad sõnumid on nähtud, siis on mõlemad IP-d täidetud (rida 3) ning igasugusel edasisel kokkupuutel antud identifikaatoriga pole enam tarvis reageerida.

Seda tabelit saab täiendada ka ajatempliga, et vanemaid kirjeid kustutama hakata. Väikeste testimismahtude juures pole see veel vajalik.

Juhtimine Et testida, on minimaalselt vaja rakendusele ka alla laaditavaid URL-e ette sööta. Selleks on mõeldavad järgmised viisid:

  • lähtekoodi sisse kirjutatud, lihtne teha aga raske hallata
  • loetakse tekstifailist rakenduse käivitamisel
  • antakse rakendusele käsurea argumendiks
  • reaalajas üle HTTP (võimaldab näiteks AJAX-iga veebiliides lisada)
  • reaalajas käsurealiidese (CLI) abil
  • ...

Testimiseks on soovitatav esialgu lihtsam variant võtta ning hiljem kui rakendus juba suuremalt osalt töötab, leida viis, mis võimaldab paindlikumalt ja massilisemalt testida.

Praktikumi kirjeldus täieneb jooksvalt semestri käigus