ITV0110 3. töö: Lihtne serverirakendus: vormid ja cgi

Allikas: Lambda
Mine navigeerimisribale Mine otsikasti

Mis tuleb teha

Kolmanda praktikumi ülesandeks on ehitada veebisüsteem, mille kaudu saab kivi-paber-käärid mängu üle võrgu mängida, ehk siis teise praktikumi teema edasiarendus veebirakendusena.

Sinu loodav süsteem on veidi sarnane näiteks facebookis mängitavale zynga pokkerile, kuid viimasest muidugi palju lihtsam.

Mängida peab saama kahel viisil:

  • Arvuti vastu (nagu teises praktikumis), kuid sedakorda peaks mängu käigu salvestama jooksvalt serverisse.
  • Teise inimese vastu, kus samuti tuleks mängu käigud serverisse salvestada.

Lisaks peab olema võimalik serverist vaadata seniste mängude tulemusi ja lihtsat statistikat:

  • kõigi seniste mängude käik
  • statistika vastase kaupa: mis on võitude, kaotuste, viikide protsent

Kokkuvõttes jaguneb töö kolmeks osaks:

  • Masina vastu mängides mängude salvestamine
  • Mängitud mängude kuvamine ja lihtne statistika
  • Inimvastase vastu üle võrgu mängimine ja samamoodi mängude kuvamine ja statistika.

Kõigi mängude korral on vaja faili salvestada ka inimese nimi, kes mängis, samuti vastase nimi (milleks võib olla ka masin). Seega on mängu alustades vaja vormilt sisestada oma nimi, mis siis serveris mängufaili kirjutatakse ja mis mängu ajal ära ei muutu. Nime võib kasutaja valida vabalt, paroole, autentimist jne jne ei ole vaja teha (kui ei ole ka otse keelatud, peaasi, et sa ei ehitaks seda enne, kui kõik muu valmis).

Praktikumi arvestamine ja hindamine

Praktikum annab maksimaalselt 15 punkti.

Esimesed kaks osa (masina vastu mängides mängude salvestamine, kuvamine ja statistika) on kohustuslik osa praktikumist ja nende korralik realiseerimine annab 7 punkti. Praktikumi ei arvestata, kui nendes osades on suuremad puudujäägid.

Omavahelise mängu realiseerimine (kolmas alamsüsteem) annab lisaks 8 punkti. Suuremate puudujääkide korral selles osas on praktikum siiski arvestatud.

Pane tähele, et selles praktikumis on kõigi ülesannete realiseerimiseks vajalik koodihulk väga väike, samas nõuab tõsist pingutust välja mõelda, kuidas kõiki asju täpselt teha ja esitada ja kuidas nad omavahel kokku käivad. Samuti võtab päris päris palju aega katsetamine ja esmatutvus võõra progekeelega.

Tehnoloogilised nõuded

  • Kõik serverirakendused tuleb realiseerida Pythonis. Vaata korra dokumentatsiooni-sisukorda, seejärel loe tutorialit.
  • Rakendus peab olema võrgus vabalt brauseriga ligipääsetav, mitte lihtsalt töötama näiteks sinu laptopis.
  • Serverarvutina võid - nagu teises praktikumis - kasutada kas dijkstrat või omaenda vabalt valitud lemmikserverit.
  • Serveris tuleb infot (loe järgmisest peatükist) hoida ühes või mitmes mängutulemuste failis.
  • Kasutada tuleb nimelt lihtsaid inimloetavaid faile, andmebaasimootoreid kasutada ei tohi (andmebaasimootorite jaoks on neljas praks).
  • Loodud veebilehed peavad sisaldama html-i, css-i ja javascripti (pluss pilte), javat ja flashi jne kasutada ei tohi.

Turvaküsimustega ei pea selles praksis tegelema! Seega on täiesti ok, kui mängija saab ise anda cgi-le parameetrid näiteks võõra mängu kohta ja sellega teiste mängu ära rikkuda, pettusi teha jne. Turvaküsimused oleks selle praksi jaoks lihtsalt liiga töö- ja tähelepanumahukad.

Miks skriptikeel (siin praksis Python) ja mitte C või Java? Eeskätt seepärast, et C ja Java jaoks juba on eraldi kursused, kus neid kasutatakse. Teiseks seepärast, et skriptikeeltes on väiksemaid/lihtsamaid veebirakendusi veidi mugavam kirjutada, kui kompileeritud keeltes.

Miks just Python? Vaata Tiobe progekeelte populaarsuse indeksit (ja lisaks ntx seda ja seda): kõige populaarsemad nn skriptikeeled on PHP ja Python. Kummagi jaoks on meil üks praktikum. PHP ja Python on üksteisest ka väga erinevad (Perl ja PHP on hoopis sarnasemad), seega on nad sobivad näited skriptikeelte spektri eri otstest.


Soovitused programmeerimiseks

Kõigepeal tutvu cgi programmide kirjutamise esmaste põhimõtetega loengumaterjalidest ja sisuliseks arusaamiseks loe cgi loengu materjalide alt teisi materjale lisaks.

Samuti on sul vaja veidi tutvuda linuxi käsurea elementaarkäskudega (kopeerimine, kustutamine, õiguste muutmine jne). Neid leiad googeldades, aga praksi jaoks peaks piisama sellest lühiõpetusest, millele tasub esimest korda lugedes kõrvale tutvuda selle tutoriali peatükkidega üks kuni viis.

Python

Kui sa ei ole varem Pythonis cgi-sid programmeerinud, tutvu kõigepealt Pythoni keele ja cgi teegiga: loe tutoriali algust (keerulised andmestruktuurid, moodulite ja klasside värgi võid esialgu lugemata jätta) ja cgi teegi õpetust.

Hea mõte on paralleelselt teha lahti Pythoni interpretaator ja katsetada kõrvale asju otse Pythoni käsureal. Kui su masinas Pythonit pole, siis installeeri!

Paljud kasulikud asjad on kirjas Pythoni teegi dokumentatsioonis. Konkreetsete küsimuste korral aitab tihti googeldamine.

NB! Pythonil on väga palju teeke ja mitmeid mittetriviaalseid keelekonstruktsioone. Sul ei lähe rõhuvat enamust nendest vaja, praktikumiks piisab väga esmastest asjadest (listid, stringid, numbrid) ning teekidest ei lähe samuti muud vaja, kui failide lugemine/kirjutamine, stringioperatsioonid ja cgi. Ära kuluta kohe aega kõigi Pythoni teekide ja detailide uurimisele, pigem alusta peale esmast tutvust koodi kirjutamist.

Arvesta, et dijkstra serveris on installeeritud Python 2.5.2, seega väldi Python 3 spetsiifiliste asjade kasutamist (vt erinevusi 2 ja 3 sarja vahel, muidu võib tekkida komplikatsioone programmide viimisel dijkstrasse. Kui sa midagi eriti keerulist ei tee, siis ei tohiks 3 sarja programmide ja 2 sarja interpretaatoriga siiski suuremaid probleeme tekkida.

Kirjuta mõni väike näiteprogramm ja katseta serveris, kuhu lõpuks süsteemi üles paned (kas siis dijkstra või oma isiklik lemmikserver).

Väga abiks on ka cgitb teegi kasutamine cgi-de mugavamaks debugimiseks: see on väga lihtne, tee seda tingimata.

Arendamine oma või arvutiklassi arvutitel

Kuna sinu süsteem peab lõpuks töötama avalikul veebiserveril, kuid arendust teed oma või arvutiklassi arvutitel, siis kuidas oleks mõistlik tööd korralda?

Peamised variandid on sellised:

  • Kirjutad kõik otse serveris, kasutades sisselogimiseks Putty-t (windows) või ssh-d (linux) ja serveris kasutad redaktoriks näiteks vi-d. Aitab, kui teed lahti mitu akent. Kõige universaalsem viis, aga nõuab vi õppimist, mis võtab aega.
  • Kirjutad faile oma masinas redaktoriga, mis lubab üle võrgu faile avada ja sulgeda, windowsis näiteks winscp abil. Katsetamiseks ja testimiseks hoiad lahti sisse logitud aknaid nagu eelmises variandis. See on suhteliselt mugav viis, kui sulle vi ei meeldi.
  • Arendad süsteemi võimalikult lõpuni windowsis valmis ja siis kannad üle serverisse ja teed vajalikke muutusi. Selleks installeeri oma arvutis python windowsile, arvutiklassides peaks see juba olemas olema. Väga abiks oleks seejuures ka veebiserveri installeerimine, näiteks
  • Kui sul on oma arvutis windows ja põhiliselt kasutad seda, siis kõige soovitavam ja pikemas perspektiivis mõistlikum viis on installeerida windowsile lisaks ubuntu linux wubi installeriga: see installer on täiesti harilik windowsi programm, mille pealepanekul tekib sinu masinasse windowsile lisaks linux. Masinat käivitades pakutakse valikut windowsi ja linuxi vahel. Niimoodi saad enda linuxi käivitada, seal apache käima panna ja arendada kogu asi enne avalikku serverisse kopeerimist valmis oma masinas. NB! Kogu see installeerimine ja süsteemiga tutvumine võtab algul paratamatult rohkem aega, kui ülaltoodud variandid: kaotad ajas lähiperspektiivis, võidad pikemas perspektiivis.
  • Ja loomulikult on võimalik kasutada oma masinas mõnda standalone unixt: linuxit, mõnda bsd-d, mac os X vms kas ainsa süsteemina või dual bootina. Kui kirjutad palju ja tihti koodi linuxi serverite jaoks, siis on see tõenäoliselt kõige mõistlikum variant.

Meeldetuletus: Python + CGI

Vormidelt saadetud data kasutamiseks on Pythonis tore imporditav moodul nimega cgi, mille funktsioonid aitavad vormiinfot söödavamal kujul sisse võtta.

Looge fail test2.py:

#!/usr/bin/python
import cgi

print "Content-type: text/html"
print

print "<html><head><title>test2.py</title></head><body><h1>Hello, World!</h1><p>Lisaparameeter oli "

formdata = cgi.FieldStorage()
if formdata.has_key("lisaparameeter"):
  print formdata['lisaparameeter'].value
else:
  print "puudu"

print ".</p></body>"

Vaadake faili brauseris:
http://dijkstra.cs.ttu.ee/~t0XXX/cgi-bin/test2.py

Parandage faili õigused omaette kirudes, et seda unustati teile teisel korral öelda ja vaadake uuesti.

http://dijkstra.cs.ttu.ee/~t0XXX/cgi-bin/test2.py http://dijkstra.cs.ttu.ee/~t0XXX/cgi-bin/test2.py?lisaparameeter=olemas

Tasub vaadata ka Kasulikke pythoni näitejuppe cgi jaoks.

Tegelik koodikirjutamine

Kõige olulisem soovitus: alusta ülesande esimesest osast - teadetetahvlist - ja realiseeri kõigepealt tema kõige lihtsam funktsionaalsus: teadetahvli kuvamine failist (algul ilma ajapiiranguta ja ridu väljadeks lahti hakkimata) ja seejärel kirje lisamine tahvlile. Kui see korralikult käib, siis täienda esialgset funktsionaalsust vastavalt tahvli nõuetele ülal.

Ära hakka korraga palju funktsionaalsust programmeerima: tee üks väike osa juurde, katseta läbi ja paranda, ning alles seejärel lisa järgmine tükk funktsionaalsust jne.

Kui tahvliosa on korras, alles siis lisa partneriga mängu alustamine ja kui see korras, asu programmeerima mängu ennast. Viimast tee jällegi väikeste tükkide kaupa.

Süsteemis on hulk funktsionaalsust, mis nõuaks justkui hulga erinevate cgi-de tegemist. Üks variant süsteemi ehitada ongi teha mitu cgi-d, teine variant on aga teha üks (või paar) cgi-d, mis saavad vormidelt ette hidden väljale pandud operatsiooninime (a la mypig.cgi?op=storetotable&name=John ...) ja siis kutsuvad välja operatsiooninimele vastavat funktsiooni sellessamas cgi-s.

Andmete esitamine ja kasutamine serveris

Info salvestamise failid on soovitav luua õigustega, kus kõik võivad faili lugeda ja kirjutada. See on turvalisuse mõttes halb, aga arendamise/debugimise mõttes hea. Siis saad ligi ise ja saavad ligi sinu programmid. Käsurealt saad teha nii:

    chmod a+rw myfile.txt

Täiesti võimalik on olukord, kus Apache poolt käivitatav cgi programm ei ole nõus sinu kataloogis uusi faile tegema: siis tuleks kas muuta oma kataloogi õigusi kõigile loetavaks/kirjutatavaks või teha failid mõnda kataloogi, kus apachel on õigused (ntx /tmp, kuid siis tuleks nende nimele panna ntx sufiksiks sinu matriklinumber, et teistega segi ei läheks) või veidi veidra, aga praksis ok variandina luua ette valmis üks tahvlifail ja suur hulk mängufaile ja siis anda neile kõigile kõigi jaoks lugemis- ja kirjutamisõigused. Sel juhul ei pea sinu programmid üldse uusi faile tegema.

Failile kirje lisamiseks võid kirjutada uue kirje lihtsalt faili lõppu uueks reaks. Vanu kirjeid pole kunagi vaja muuta!

Igale kirjele võib panna lisaväljana (ntx esimeseks) kaasa kirje loomise aeg.

Faili lugemisel on üldiselt hea mõte kasutada f.readline() funktsiooni, võid soovi korral kasutada ka csv teeki, mille abil faili tabeliks lahti hakkimine nõuab veidi vähem koodikirjutamist (aga mitte tingimata palju vähem sinu aega).

Aja määramisel on sul kõige praktilisem kasutada time.time() funktsiooni (otsi see mahukast ajateegist välja: see annab lihtsalt aja ühe numbrina, sekundites peale aastat 1970 vms. Selle numbri saad siis lihtsalt tahvlifaili kirjutada. Lugemisel on seda samuti lihtne võrrelda (ja liita/lahutada) hetkeajaga.

NB! Ära hakka jändama keerukate aasta/minuti/ajatsooni jne jne meetoditega: need on keerulised, nende uurimine võtab hulga aega ja praksis neid vaja ei lähe (mis ei tähenda, et huvi korral ei võiks neid uurida :).

Stringi muutmine numbriks on lihtne (int("12") või float("12")) ning samamoodi on lihtne numbri muutmine stringiks (string(12) või string(12.5)).


Eelmise aasta versioon

Eelmise aasta versiooni, mis on mitmes osas sarnane, kuid mitmes osas erinev, leiad siit.