Ohjelmoinnin peruskurssien laaja oppimäärä

Samankaltaiset tiedostot
Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä, kevät

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Palomuurit. Palomuuri. Teoriaa. Pakettitason palomuuri. Sovellustason palomuuri

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Kiertokysely. Sulautetut järjestelmät Luku 2 Sivu 1 (??)

Ohjelmoinnin perusteet Y Python

Luento 5. Timo Savola. 28. huhtikuuta 2006

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

TCP/IP-protokollat ja DNS

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssi Y1

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 6: Python

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Harjoitustyö: virtuaalikone

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin perusteet Y Python

3. Kuljetuskerros 3.1. Kuljetuspalvelu

Ohjelmoinnin peruskurssien laaja oppimäärä

Zeon PDF Driver Trial

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

SSH Secure Shell & SSH File Transfer

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin perusteet Y Python

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Tehtävä 2: Tietoliikenneprotokolla

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin perusteet Y Python

ELEC-C7241 Tietokoneverkot Ohjelmointiprojekti

Ohjelmoinnin perusteet Y Python

Kirjoita oma versio funktioista strcpy ja strcat, jotka saavat parametrinaan kaksi merkkiosoitinta.

Tietokanta (database)

Ohjelmoinnin perusteet Y Python

Ohjelmistojen mallinnus Ohjelmistoarkkitehtuuri Harri Laine 1

AJAX-konsepti AJAX. Asynkronisuus. Nykyisten web-ohjelmien ongelmia. Asynchronous JavaScript And XML

811120P Diskreetit rakenteet

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

CODEONLINE. Monni Oo- ja Java-harjoituksia. Version 1.0

Salausmenetelmät (ei käsitellä tällä kurssilla)

4. Luento: Prosessit ja säikeets. Tommi Mikkonen,

Tutoriaaliläsnäoloista

Unix-perusteet. Tiedosto-oikeudet

Esimerkkiprojekti. Mallivastauksen löydät Wroxin www-sivuilta. Kenttä Tyyppi Max.pituus Rajoitukset/Kommentit

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

ELM GROUP 04. Teemu Laakso Henrik Talarmo

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit

KServer Etäohjaus Spesifikaatio asiakaspuolen toteutuksille

Netemul -ohjelma Tietojenkäsittelyn koulutusohjelma

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014

jotakin käyttötarkoitusta varten laadittu kokoelma toisiinsa liittyviä säilytettäviä tietoja

Ohjelmoinnin perusteet Y Python

Tietotekniikan valintakoe

Ohjelmoinnin peruskurssien laaja oppimäärä

PRINCIPLES OF PROGRAMMING LANGUAGES - DEBUGGER

Tietokone. Tietokone ja ylläpito. Tietokone. Tietokone. Tietokone. Tietokone

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1

Graafisen käyttöliittymän ohjelmointi Syksy 2013

tään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla

Ohjelmointikielet ja -paradigmat 5op. Markus Norrena

Ohjelmoinnin peruskurssi Y1

SEPA REFAKTOROINTI Antti Ahvenlampi, 57408L Erik Hakala, 57509T

Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python

Ohjelmoinnin peruskurssien laaja oppimäärä

Action Request System

BaseMidlet. KÄYTTÖOHJE v. 1.00

VERKON ASETUKSET SEKÄ WINDOWSIN PÄIVITTÄMINEN

Laitteessa tulee olla ohjelmisto tai uudempi, tarvittaessa päivitä laite

Sisältö. 22. Taulukot. Yleistä. Yleistä

2. Lisää Java-ohjelmoinnin alkeita. Muuttuja ja viittausmuuttuja (1/4) Muuttuja ja viittausmuuttuja (2/4)

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä

TAMPEREEN TEKNILLINEN YLIOPISTO Digitaali- ja tietokonetekniikan laitos. Harjoitustyö 4: Cache, osa 2

12. Näppäimistöltä lukeminen 12.1

Transkriptio:

Ohjelmoinnin peruskurssien laaja oppimäärä Luento 4: Verkko-ohjelmointi, tapahtumapohjainen ohjelmointi, lisää ohjelmien suunnittelusta Riku Saikkonen (osa kalvoista on suoraan ei-laajan kurssin luennoista) 15. 2. 2012

Sisältö 1 Verkko-ohjelmointia: socketit 2 Useammasta paikasta lukeminen 3 Tapahtumapohjainen ohjelmointi 4 Lisää ohjelmien suunnittelusta

(ei-laajan kurssin kalvo: luento 5 sivu 21) Yksinkertainen palvelin import socket # Import socket module server = socket.socket() # Create a socket object host = socket.gethostname() # Get local machine name port = 12345 # Reserve a port for your service. server.bind((host, port)) # Bind to the port server.listen(5) # Now wait for client connection. while True: client, addr = server.accept() # Establish connection with client. print 'Got connection from', addr infile = open('esimerkki.txt', 'r') for line in infile: client.send(line) client.close() # Close the connection 14:58

(ei-laajan kurssin kalvo: luento 5 sivu 22) Ja asiakas import socket import StringIO # Import socket module client = socket.socket() # Create a socket object host = socket.gethostname() # Get local machine name port = 12345 # Reserve a port for your service. client.connect((host, port)) message = StringIO.StringIO() chunk = client.recv(10) while chunk: message.write(chunk) chunk = client.recv(10) print message.getvalue() client.close() # Close the socket when done 14:58

Millaisia verkkoyhteyksiä on? edellinen esimerkki käytti Internetin TCP/IP-protokollaa se on tietovirtapohjainen (stream) eli avattu yhteys näyttää tiedostolta (sisään ja ulos kulkee jono tavuja) oikeasti data liikkuu paketeissa (usein 1500 tavua), joita voi kadota tai joiden järjestys voi muuttua matkalla TCP-protokolla järjestää paketit ja pyytää tarvittaessa uudelleenlähetyksiä (ei näy ohjelmalle) toinen, harvinaisempi vaihtoehto on UDP/IP pakettipohjainen (datagram): lähetetään ja vastaanotetaan tavujonojen sijaan kokonaisia paketteja pakettien lähetykseen ja vastaanottoon on useimmissa kielissä omat funktionsa ohjelma saa paketit kokonaisina ja sitä mukaa kun niitä tulee siis paketteja voi jäädä tulematta tai tulla eri järjestyksessä käytetään esim. reaaliaikaista ääni- ja videodataa siirrettäessä muutama muukin tämän tason protokolla on

Portit ja yhteydet yhteyden muodostaminen TCP:ssä ja UDP:ssä: 1 Palvelin kuuntelee (listen) oman IP-osoitteensa (jonkin tai kaikkien niistä) tiettyä porttia, esim. 12345 2 Asiakas ottaa yhteyden (connect) tähän IP-osoitteeseen ja porttiin 3 Palvelin hyväksyy (accept) tämän yhteydenottopyynnön (voi hyväksyä useammankin pyynnön: niistä tulee erilliset yhteydet) yhteydenmuodostuksen jälkeen yhteys on symmetrinen: kumpi tahansa voi lähettää dataa toiselle tai sulkea yhteyden portti (port) on numero väliltä 165535 useimmiten kuunnellaan tietyssä portissa, joka kuuluu jollekin palvelulle (esim. useimmat HTTP-palvelimet portissa 80) avattu yhteys (connection) on nelikko, jossa on kummankin pään IP-osoite ja kummankin pään valitsema portti asiakas valitsee itselleen yleensä satunnaisen portin porttiparilla erotetaan samojen koneiden väliset yhteydet toisistaan esim. WWW-palvelimeen voisi olla yhtäaikaiset yhteydet (12.12.12.12, 1025, 1.2.3.4, 80) ja (12.12.12.12, 1524, 1.2.3.4, 80)

Nimipalvelin TCP/IP ja UDP/IP toimivat IP-osoitteilla (numeroita) koneiden tai palveluiden nimet muutetaan IP-osoitteiksi kysymällä niitä nimipalvelimelta (domain name server) Internetissä on hierarkia nimipalvelimia, joilta nimiä kysytään esim. www.aalto.fi: juurinimipalvelin (root server) tietää fi-nimipalvelimen osoitteen, joka tietää aalto.fi-nimipalvelimen osoitteen, joka tietää www.aalto.fi-koneen osoitteen tämä on harvoja osia Internetistä, joka on hallinnollisesti keskitettyä esim. fi-nimipalvelin päättää kaikista.fi-päätteisistä osoitteista (vaikka se yleensä delegoi päätökset alemman tason palvelimille) kuormitussyistä ylempien tasojen nimipalvelimia on monta samanlaista (esim. juurinimipalvelimia kymmeniä) käytännössä lähiverkossa on melkein aina apunimipalvelin, jolta voi kysellä nimiä ja joka kysyy niitä eteenpäin muilta ja tallettaa kyselyiden tulokset välimuistiinsa, joten samojen koneiden nimiä ei tarvitse ei tarvitse koko ajan kysellä periltä asti

Nimipalvelin ohjelmoijan näkökulmasta nimipalvelin ja siihen liittyvät protokollat piilotetaan enimmäkseen ohjelmoijalta: joko kirjastoissa on kutsu, jolla voi tehdä nimipalvelukyselyn tai yhteydenmuodostuskomennolle voi antaa IP-osoitteen sijaan nimen käytännön rajapintaongelma: useimmiten nimipalvelukysely jää odottamaan vastausta (blocking) siis ohjelma pysähtyy siksi aikaa kirjastorajapinnat, joissa ohjelma voisi tehdä jotain odotuksen aikana, ovat harvinaisia jos tämä on ongelma, nimipalvelukyselyt voi tehdä esim. eri säikeessä jotkin ohjelmat, esim. WWW-selaimet, käynnistävät oman aliprosessin nimipalvelukyselyitä varten (se pitää lisäksi tulokset tallessa muistissaan)

TCP:n päällä olevat protokollat TCP/IP siis tarjoaa yhteyden, jossa voi siirtää vapaamuotoista dataa (tavuja tai merkkejä) edestakaisin sen päälle on Internetissä tehty paljon sovellustason protokollia esim. HTTP, jossa asiakas pyytää webbisivua (avaa palvelimeen yhteyden ja lähettää URLin tietyssä muodossa) ja palvelin vastaa sivun sisällöllä tai NNTP, jolla luetaan ja kirjoitetaan nyyssejä yhden rivin pituisilla ASCII-komennoilla nämä on dokumentoitu ns. RFC-dokumenteissa, joista osa on valittu Internet-standardeiksi useimmat ovat asiakaspalvelin-tyyppisiä joskus käytetään myös peer-to-peer-palveluita, joissa molemmat päät ovat samanarvoisia yhteydenmuodostus on näissä monimutkaisempaa, varsinkin palomuurien ja osoitemuunnosten (NAT) läpi käytetään esim. joissain verkkopeleissä ja IP-puheluissa

Paikalliset socketit periaatteessa socketit eivät ole vain Internet-yhteyksiä varten varsinkin Unix/Linux-koneissa niitä käytetään myös koneen sisäiseen kommunikointiin ohjelmien välillä Unix domain socket on kuten TCP, mutta paikallinen: portin tilalla on (yleensä) tiedoston nimi, jossa kuunnellaan ja johon otetaan yhteyttä tiedosto on tyypiltään socket ( s ls-komennossa) muodostettu yhteys toimii kuten TCP, mutta koneen sisällä lisäksi yhteydestä saa selville sen toisen pään käyttäjänimen (sillä tai tiedoston oikeuksilla voi rajoittaa sockettiin pääsyä) etuna on varsinkin viimeinen: UDP- ja TCP-yhteyksiin pääsee ainakin koko sama kone, tavallisesti myös koneen ulkopuolelta UDP- ja TCP-yhteydet voi rajoittaa samasta koneesta (mutta muiltakin käyttäjiltä) tuleviksi vaihtamalla kuunneltava osoite (listen address, bind address) localhost-osoitteeksi 127.0.0.1

Vinkkejä kokeiluun komentoriviohjelmilla nc ja socat voi avata yksittäisiä verkkoyhteyksiä kummin päin tahansa ohjelmilla host ja dig voi tehdä nimipalvelukyselyjä omalla koneella (ylläpito-oikeuksilla) esim. ohjelmalla tcpdump voi seurata koneen lähettämiä ja vastaanottamia paketteja varoitus: kuuntelevaan TCP- tai UDP-sockettiin pääsee koko maailma! paitsi jos palomuuri sattuu estämään (silloinkin pääsee sama kone ja yleensä koko lähiverkko) kokeilut kannattaa tehdä esim. kotikoneella, joka on irti verkosta varsinkin kuunteleva ja pitkään päällä oleva palvelin on tietoturvariski (oleta, että verkosta tuleva syöte on vihamielistä!) Aalto-koneilla Työaseman tai palvelimen ulkopuolelle näkyvien palveluprosessien pystyttäminen edellyttää tietojärjestelmän omistajan lupaa. (käyttöpolitiikka 3. 6. 2010) lisää verkkoyhteyksistä esim. kurssin T-110.2100 luentokalvoilta

(ei-laajan kurssin kalvo: luento 5 sivu 23) Verkkoyhteydet Socket-kirjaston päälle on rakennettu muita kirjastoja, jotka helpottavat asioiden tekemistä. Esim. urllib on tiedostojen hakuun www:stä import urllib infile = urllib.urlopen('http://www.cse.hut.fi/fi/opinnot/t1061215/'\ + '2012_external/harjoitukset/kierros_3x/harj_1/game.txt') print infile.read() 14:58

(ei-laajan kurssin kalvo: luento 2 sivu 19) Security injections Seuraava materiaali löytyy kokonaisuudessaan: http://triton.towson.edu/~cssecinj/secinj/?page_id=170 Kolme tärkeää turvallisuusriskiä Kokonaislukuvirheet Kun arvo on liian suuri muuttujaan Ei ongelma Pythonissa Syötteen oikeellisuus Syötteen oikeellisuutta ei tarkasteta Puskurin ylivuoto Sijoitetaan tietoa muuttujalle varatun alueen ulkopuolelle 11:31 Ei ongelma Pythonissa, aiheuttaa virheen

(ei-laajan kurssin kalvo: luento 2 sivu 20) Syötteen oikeellisuus Ohjelman syöte voi olla turvariski ja vakavan virheen syy Kaikkia syötteitä pitäisi käsitellä mahdollisina vaaratekijöinä Oikein muotoiltu syöte voi saada ohjelman suorittamaan laittomia käskyjä Jos syötteen tyyppiä, määrää ja rakennetta ei tarkisteta, riski on olemassa. 11:31

(ei-laajan kurssin kalvo: luento 2 sivu 23) Miten tarkistan syötteen? Tarkista kaikki syötteet Lukualue? Järkevä? Ongelma-arvo? (esim. nolla jakajaan) Muoto? Reagoi virhelliseen syötteeseen oikein Virheestä pitää toipua ja kysyä uudelleen tai muuten jatkaa eteenpäin. Väärän syötteen katkaiseminen tai muotoilu sopivaksi saattaa aiheuttaa lisäharmia 11:31

Sisältö 1 Verkko-ohjelmointia: socketit 2 Useammasta paikasta lukeminen 3 Tapahtumapohjainen ohjelmointi 4 Lisää ohjelmien suunnittelusta

Ei-blokkaava I/O normaalisti luku tai kirjoitus siis jää tarvittaessa odottamaan eli blokkaa (blocks) ei-blokkaava (non-blocking) I/O toimii useimmissa kielissä joko niin, että lukumetodi/funktio palaa heti ja kertoo lukeneensa 0 tavua, jos dataa ei ollut tai niin, että erillinen metodi/funktio kertoo, onko dataa saatavilla kirjoitusmetodi vastaavasti kertoo, että sai 0 tavua kirjoitettua mutta käytännössä kirjoitukset ovat melkein aina puskuroituja jossain (esim. käyttöjärjestelmässä tai laitteissa), jolloin 0 tavua tarkoittaa että kirjoituspuskuri on täynnä blokkaavassa I/O:ssa kirjoituskin voi blokata, jos puskuri on täynnä ongelmana on, että jos lukeminen tai kirjoittaminen ei jää odottamaan, ohjelman pitää yleensä yrittää sitä uudelleen jatkuvasti esim. silmukassa useimmiten parempi ratkaisu on select (josta seuraavaksi)

Useammasta paikasta lukeminen entä jos ohjelma haluaa lukea monesta paikasta sitä mukaa kun niistä tulee dataa? esim. useammasta auki olevasta verkkoyhteydestä tai (Unixissa) tiedostoista, laitteista, aliprosesseilta tms. tyypillisesti joko jaetaan ohjelma useaan säikeeseen niin että jokainen lukee vain yhtä datalähdettä tai rajapinnassa on funktio, joka tutkii useampaa datalähdettä ja kertoo, mistä niistä on juuri nyt saatavilla dataa tämän nimi on usein select tai poll tätä pitää kutsua silmukassa, jossa tehdään jotain kaikelle saatavilla olevalle datalle jos mistään ei tule dataa, se jää odottamaan vähäksi aikaa (aikarajan voi antaa kutsussa) tarkempia ohjeita Pythonin selectistä: http://docs.python.org/howto/sockets.html ja http://docs.python.org/library/select.html

select-esimerkki: apufunktioita chatserver.py import socket import select class Client(object): def init (self, sock, addr): self.sock = sock self.addr = addr self.wpos = 0 clients = [] chatbuf = bytearray('welcome\n') def findclient(sock): return [c for c in clients if c.sock == sock][0] def removeclient(sock): global chatbuf sockc = findclient(sock) chatbuf += '\n[closed ' + repr(sockc.addr) + ']\n' clients.remove(sockc) def addclient(sock, addr): global chatbuf chatbuf += '\n[connect from ' + repr(addr) + ']\n' clients.append(client(sock, addr))

select-esimerkki: pääohjelma chatserver.py def main(): global chatbuf server = socket.socket() server.setsockopt(socket.sol_socket, socket.so_reuseaddr, 1) server.bind(('', 12345)) server.listen(10) while True: readers = [server] + [c.sock for c in clients] writers = [c.sock for c in clients if c.wpos < len(chatbuf)] rr, rw, err = select.select(readers, writers, readers) for e in err: removeclient(e) e.close() for r in rr: if r == server: clientsock, addr = r.accept() addclient(clientsock, addr) else: data = r.recv(1024) if len(data) == 0: removeclient(r) r.close() chatbuf += data for w in rw: cw = findclient(w) sent = cw.sock.send(chatbuf[cw.wpos:]) cw.wpos += sent

Sisältö 1 Verkko-ohjelmointia: socketit 2 Useammasta paikasta lukeminen 3 Tapahtumapohjainen ohjelmointi 4 Lisää ohjelmien suunnittelusta

Tapahtumiin perustuva lukeminen monesta paikasta lukemisen ongelmaan on myös toisenlainen ratkaisu: lukemisen voi kääntää toisin päin ei tehdäkään niin että ohjelma lukee halutessaan dataa jonkinlaisella read-funktiolla eikä edes omassa selectiä käyttävässä silmukassa vaan että ohjelma rekisteröi rajapinnalle callback-funktion (takaisinkutsun), jota rajapinta kutsuu aina kun lisää dataa on saatavilla siis: normaalisti ohjelma vetää rajapinnalta lisää dataa silloin, kun ohjelmalle sopii; mutta tässä menetelmässä rajapinta työntää ohjelmalle dataa silloin, kun sitä on saatavilla tällaisen rajapinnan huono puoli on, että datan käsittely tapahtuu eri paikassa kuin lukemisen käynnistäminen, joten koodin etenemistä on vaikeampi seurata

Esimerkki tapahtumiin perustuvasta lukemisesta wget-ohjelman tiedonsiirron etenemistä kuvaava palkki (progress bar) on olio, jonka update-metodia muu ohjelma kutsuu aina kun siirto etenee wget-1.12/src/progress.c metodi saa kaksi argumenttia: howmuch = montako tavua edellisen kutsun jälkeen on saatu, ja dltime = kauanko siirto on tähän mennessä kestänyt muu ohjelma siis työntää tälle oliolle dataa (tavumääriä), ja olio päivittää palkkia aina kun tiedonsiirto on edennyt riittävästi toinen vaihtoehto olisi, että palkin piirtämistä varten olisi silmukka, joka kysyy muulta ohjelmalta säännöllisesti, kuinka paljon dataa on tullut, ja piirtää palkin tämän mukaan tämä on esimerkki ohjelman sisäisestä tapahtumarajapinnasta tyypillisemmin jokin ohjelman ulkopuolinen kirjasto haluaa työntää eikä vetää dataa tai ohjelman sisällä on yksi select-silmukka joka kutsuu ohjelman funktioita pienissä paloissa

Tapahtumapohjaisuus graasissa käyttöliittymissä useimmiten graasissa ohjelmissa ohjelman suoritusmalli on erilainen kuin tavallisissa ohjelman kannalta katsottuna (yksinkertaistaen): main-funktiota tms. ei ole (tai se tekee vain alustuksen ja hyppää GUI-kirjaston pääsilmukkaan) koodista ei näy suoritusjärjestystä, jossa asiat tapahtuvat vaan ohjelma toimii pelkästään reagoimalla yksittäisiin tapahtumiin (event, joskus signal) esim. käyttöliittymän napin painaminen käynnistää tätä tapahtumaa käsittelevän koodin ei siis niin päin, että koodin keskellä olisi read-kutsu tms., joka jäisi odottamaan ja palauttaisi käyttäjältä saadun syötteen tapahtumankäsittelijän pitää usein päätellä, missä tilassa ohjelma on (eli mitä napin pitäisi nyt tehdä) useimmiten yksittäiset tapahtumankäsittelijät ovat melko yksinkertaisia ja lyhytkestoisia

Mitä oikeasti tapahtuu? miten edellä kuvattu tapahtumapohjainen suoritusmalli toteutetaan? GUI-ohjelmassa on main, joka luo käyttöliittymäkomponentit ja jää lopulta silmukkaan (ns. event loop) odottamaan tapahtumia tämä silmukka on normaalisti GUI-kirjaston sisällä eli ei suoraan näy itse ohjelmassa silmukka lähettää kunkin tapahtuman sen käsittelijälle tapahtumankäsittelijä on funktio tai metodi, jonka ohjelmoija on esim. käyttöliittymäkomponenttia luodessaan antanut tee nappi, jonka painalluksista kutsutaan tätä funktiota tällainen funktio on nimeltään takaisinkutsu (callback function) sitä ei (yleensä) kutsuta suoraan ohjelmasta käsin tapoja ajatella: suoritus on asynkronista (ei siis tahdissa käsky kerrallaan) tai reaktiivista (reagoidaan tapahtumiin eikä jäädä kesken koodin odottamaan vastausta)

Peräkkäin vai yhtäaikaa? yleensä tapahtumankäsittelijöitä kutsutaan peräkkäin ei siis yhtäaikaa eli rinnakkain tyypillisesti käyttöliittymä ei reagoi, kun suoritus on tapahtumankäsittelijäfunktion sisällä joten funktion on syytä olla nopea entä jos GUI-ohjelmassa haluaa tehdä jotain pitkäkestoista? kirjastoissa on erikseen tapa määritellä taustalaskentaa (kutsu tätä aina kun tapahtumia ei ole saatavilla) sekä ajastettuja tapahtumia (kutsu tätä sekunnin välein) mutta näitäkin kutsutaan muun tapahtumakäsittelyn joukossa, joten yksittäisen funktion suoritus ei saa kestää kauaa (muuten käyttöliittymä jää jumiin siksi aikaa) pitkäkestoinen laskenta pitää siis paloitella lyhyisiin osiin toinen tapa on käyttää rinnakkaisuutta (josta myöhemmin)

I/O GUI-kirjastoissa entä jos graanen ohjelma haluaa myös lukea verkkoyhteyksiä? readia, recv:ä tms. ei saa itse kutsua (blokkaavasti) koska silloin käyttöliittymätapahtumia ei käsiteltäisi odotusaikana (eli odotus tapahtuisi muualla kuin GUI-kirjaston silmukassa) GUI-kirjastot osaavat itse odottaa verkkoyhteyksiä (tiedostoja) ja kutsua tapahtumankäsittelijää kun luettavaa tulee yhteydestä x voi lukea dataa tulee siis oma tapahtumansa tyypillisesti rajapinnasta löytyy funktio, jolle annetaan avoin verkkoyhteys (tai tiedosto) ja takaisinkutsufunktio itse asiassa (Unixissa) GUI-kirjaston tapahtumankäsittelysilmukka kutsuu yleensä itse selectiä, jossa käyttöliittymätapahtumat näkyvät erikoisina tiedostoina (X11-ikkunointijärjestelmässä välissä on oikea socket-yhteys) eli yhteenvetona selectin käyttäminen (kuten muutkin pitkäkestoiset toiminnot) pitää delegoida GUI-kirjastolle

Sisältö 1 Verkko-ohjelmointia: socketit 2 Useammasta paikasta lukeminen 3 Tapahtumapohjainen ohjelmointi 4 Lisää ohjelmien suunnittelusta

(ei-laajan kurssin kalvo: luento 2 sivu 8) Sunnittelu Suunnittelussa ohjelma kannattaa jakaa jonkinlaisiin alijärjestelmiin Tarpeettomia riippuvuuksia näiden välillä vältettävä Sykliset riippuvuudet voivat aiheuttaa ongelmia Esimerkki : Käyttöliittymän ja logiikan erottaminen Logiikka (pelin logiikka, numeroilla tehtävä simulointi, tietokanta jne) kirjoitetaan itsenäiseksi osaksi joka ei tiedä millaisella käyttöliittymällä sitä käytetään. Pohdi millaisia metodeja luokkien julkiseen rajapintaan tarvitaan että eri käyttöliittymät voivat ohjata logiikkaa ja hekea tietoa Käyttöliittymä (GUI) on oma osionsa. Käyttäjän toimet kutsuvat GUI:n kautta logiikan metodeita. Käyttöliittymä hakee logiikalta ruudulla näyttämänsä tavaran. GUI ohjaa, pyytää tietoa Aivot 11:31

(ei-laajan kurssin kalvo: luento 2 sivu 10) Suunnittelu Model-View-Controller Tämä suunnittelumalli menee vielä askeleen pidemmälle, erottaen GUI:n (Controller) osat jotka muuttavat mallia (Model) ja osat jotka vain esittävät mallin sisältämää tietoa(view) Controller Tiedot päivittyivät ohjaus muutoskäskyt View Esitettävän datan kysely Tiedot päivittyivät, käy kysymässä Model 11:31

Lisää ModelViewControllerista Model, malli: sisältää ohjelman tallettaman datan ja tavat kysellä ja muuttaa sitä usein myös lähettää tietoja muutoksista niitä pyytäneille datan esitysmuotoa voisi vaihtaa pelkkää mallia muuttamalla joskus osa mallista on tietokannassa View, näkymä: käyttöliittymä tai erityisesti sen osa, joka näyttää asioita sillä voi olla omaa tilaa, jota esim. ei talleteta (mikä kohta datasta on tällä hetkellä näkyvissä?) perusideaan kuuluu, että näkymiä voisi olla yhtäaikaisesti monta erilaista (joskus onkin) Controller, ohjain: mallia muuttavat osat ohjelmasta (käyttöliittymästä ja automaattisesti esim. laskemalla) ei kerro näkymälle datasta (näkymä hakee ne mallilta)

(ei-laajan kurssin kalvo: luento 2 sivu 11) Suunnittelu Turhien riippuvuuksien välttäminen kannattaa myös alemmilla tasoilla Toisaalta samasta tiedosta ei yleensä kannata pitää useita kopioita Yhtä päivitettäessä pitää aina päivittää muutkin Myös riippuvasta datasta olevat kopiot voivat olla ongelmallisia Tällöin riippuvan datan turha uudelleenlaskeminen voi olla hyödyllistä. 11:31

Lisää suunnitteluvaihtoehtoja joskus suunniteltava ohjelma kannattaa jakaa osiin useampi ohjelma tai (yleiskäyttöisiä) kirjastoja + ohjelma joskus näitä osia voi yhdistää monella tavalla usein niitä voi käyttää yksinään (ei välttämättä kätevästi) hyödyllinen ajattelutapa: rajapinta voi olla kieli oikea pieni kieli, jota esim. tulkataan tai kokoelma funktioita, jotka on nimetty niin että niitä käyttävä koodi muistuttaa kieltä (esim. SICPin picture language-esimerkki) tai niin yleiskäyttöisiä funktioita, että niitä voi käyttää yhtä monipuolisesti kuin kieltä (esim. listankäsittelyfunktiot?) joskus kannattaa yleistää jos rajapinta vaikuttaa monimutkaiselta, voi olla parempi jakaa se geneerisempiin osiin mutta liika abstrahointi johtaa vaikeasti lähestyttävään koodiin

(ei-laajan kurssin kalvo: luento 2 sivu 12) Suunnittelu Mistä tiedetään, mitä luokkia pitäisi laatia tietyn ongelman ratkaisemiseksi? Millaisia kenttiä ja metodeja niille tulee? Ei ole yhtä parasta ratkaisua. Suunnittelutavoitteet voivat olla ristiriitaisia tasapainottelu, kompromissit. Ei ole menetelmää, jolla päästään varmasti hyvään tulokseen. Ei ole yleispätevää tapaa selvittää, onko jokin ratkaisu hyvä tai huono. Useimmille nyrkkisäännöille löytyy tapauksia, joissa kannattaakin toimia toisin. 11:31

(ei-laajan kurssin kalvo: luento 2 sivu 13) Substantiivimenetelmä Yksi kirjallisuudessa esitelty tekniikka tehdä ensimmäinen malli ohjelman luokkarakenteesta 1)Kirjoitetaan lyhyehkö mutta tarkka sanallinen kuvaus ohjelman toimintavaatimuksista 2)Etsitään kuvauksesta kaikki verbit ja substantiivit 3)päätetään mitkä substantiiveista ovat luokkia, mitä näiden luokkien kenttiä 4)päätetään mitkä verbeistä ovat luokkien metodeja Vain alustava malli Kun ensimmäinen malli on saatu pohdittua niin sitä ryhdytään muokkaamaan ja tarkistetaan voidaanko sen avulla todella toteuttaa vaatimukset. 11:31

(ei-laajan kurssin kalvo: luento 2 sivu 17) Käyttötapaukset (use case) ja mallin kehittäminen Kun alustava malli on rakennettu, kokeile sitä jo ennen koodausta erilaisilla käyttötavoilla Esim. Kuinka ja mitä metodeja kutsuttaisiin jos käyttäjä siirtää rahaa tililtä toiselle? Miten metodit tilisiirrossa kutsuvat toisiaan? Millaisia parametreja pitäisi laittaa? Löytyykö luokista tarvittavaa dataa. Muokkaa ja tarkenna mallia käymällä läpi joukko erilaisia käyttötapauksia. Kun olet tyytyväinen alustavaan malliin voit aloittaa koodailun. Malli tulee varmasti muuttumaan vielä koodausvaiheessa 11:31

Pohdintaa ohjelman suunnittelu on eniten luovuutta ja kekseliäisyyttä vaativa osa ohjelmoinnissa ellei sitten sen suunnittelu, mitä ohjelman pitäisi tehdä... tarkkoja sääntöjä ei ehkä kannata edes etsiä? suunnittelu on osin taidetta (kuinka paljon?) onkohan ohjelmoinnissa tyylisuuntia kuten taidehistoriassa? (esim. olio-ohjelmointi?) useimmissa taidemuodoissa tyylisuunnista yksi kerrallaan on hallitseva (jonkin aikaa ja tietyllä alueella) joskus suunnittelun taustalla on (ollut?) pyrkimys löytää oikea tapa tehdä jokin tietty asia, The Right Thing esim. SICPin symbolinen derivoija taisi syntyä 60-luvulla näin suunnittelua oppii harjoittelemalla, mutta myös lukemalla muiden tekemiä ohjelmia