HOJ RMI = Remote Method Invocation

Samankaltaiset tiedostot
Rinnakkaisohjelmointi kurssi. Opintopiiri työskentelyn raportti

JavaRMI 1 JAVA RMI. Rinnakkaisohjelmoinnin projekti 1 osa C Tekijät: Taru Itäpelto-Hu Jaakko Nissi Mikko Ikävalko

Verkko-ohjemointia. TCP vs. UDP Socket, ServerSocket Datagrammit RMI

Projekti 1 Säikeet ja kriittisen vaiheen kontrollointi javalla

Rajapinta (interface)

Java-API, rajapinnat, poikkeukset, UML,...

HOJ Kertausluento. Ville Leppänen. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.1/58

14. Poikkeukset 14.1

Ohjelmointi 2 / 2010 Välikoe / 26.3

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Rinnakkaisohjelmointi, Syksy 2006

14. Poikkeukset 14.1

Mikä yhteyssuhde on?

HOJ J2EE & EJB & SOAP &...

HSMT J2EE & EJB & SOAP &...

HOJ Haja-aiheita. Ville Leppänen. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.1/10

HSMT Tietokannoista. Ville Leppänen. HSMT, c Ville Leppänen, IT, Turun yliopisto, 2008 p.1/32

Olio-ohjelmointi Javalla

Poikkeustenkäsittely

Metodien tekeminen Javalla

Kompositio. Mikä komposition on? Kompositio vs. yhteyssuhde Kompositio Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma

HOJ Säikeet (Java) Ville Leppänen. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.1/55

Tehtävä 1. Tehtävä 2. Arvosteluperusteet Koherentti selitys Koherentti esimerkki

812341A Olio-ohjelmointi Peruskäsitteet jatkoa

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

Listarakenne (ArrayList-luokka)

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Rajapinnat ja sisäluokat

1 Tehtävän kuvaus ja analysointi

Luento 6. T Ohjelmoinnin jatkokurssi T1 & T Ohjelmoinnin jatkokurssi L1. Luennoitsija: Otto Seppälä

T Henkilökohtainen harjoitus: FASTAXON

Hajautettujen sovellusten muodostamistekniikat, TKO_2014 Johdatus kurssiin

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely

public static void main (String [] args)

A) on käytännöllinen ohjelmointitekniikka. = laajennetaan aikaisemmin tehtyjä luokkia (uudelleenkäytettävyys)

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen

10 Lock Lock-lause

Ohjelmointi 2 / 2008 Välikoe / Pöytätestaa seuraava ohjelma.

Periytyminen (inheritance)

on ohjelmoijan itse tekemä tietotyyppi, joka kuvaa käsitettä

OHJ-5010 Hajautettujen järjestelmien perusteet

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

Monitorit -projekti Rinnakkaisohjelmointi

Ohjelmointityö 3. Mikko Laamanen

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista.

17. Javan omat luokat 17.1

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

Ohjelmoinnin jatkokurssi, kurssikoe

Tietokannat II -kurssin harjoitustyö

20. Javan omat luokat 20.1

Sisällys. 20. Javan omat luokat. Java API. Pakkaukset. java\lang

Liite 1. Projektin tulokset (Semaforit Javassa) Jukka Hyvärinen Aleksanteri Aaltonen

Lista luokan sisällä

Luokan sisällä on lista

Javan perusteita. Janne Käki

Sisältö. 2. Taulukot. Yleistä. Yleistä

812341A Olio-ohjelmointi, IX Olioiden välisistä yhteyksistä

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

Vertailulauseet. Ehtolausekkeet. Vertailulauseet. Vertailulauseet. if-lauseke. if-lauseke. Javan perusteet 2004

16. Javan omat luokat 16.1

Toisessa viikkoharjoituksessa on tavoitteena tutustua JUnit:lla testaukseen Eclipse-ympäristössä.

Javan semaforit. Joel Rybicki, Aleksi Nur mi, Jara Uitto. Helsingin yliopisto

Javan GUI Scratchaajalle

Metodit Arvotyyppi. Metodit Arvotyyppi. Metodit Parametrit. Metodit Parametrit. Metodit Kuormittaminen. Metodit Kuormittaminen. Javan perusteet

Java ja grafiikka. Ville Sundberg

JAVA-OHJELMOINTI 3 op A274615

KOHDELUOKAN MÄÄRITTELY

Olio-ohjelmointi Virhetilanteiden käsittely

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo

Pino S on abstrakti tietotyyppi, jolla on ainakin perusmetodit:

9. Periytyminen Javassa 9.1

Luokat ja oliot. Ville Sundberg

8. Näppäimistöltä lukeminen 8.1

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

Java kahdessa tunnissa. Jyry Suvilehto

JAVA on ohjelmointikieli, mikä on kieliopiltaan hyvin samankaltainen, jopa identtinen mm. C++

7. Oliot ja viitteet 7.1

1. Omat operaatiot 1.1

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

Sisältö. Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 6.2

9. Periytyminen Javassa 9.1

YHTEYSSUHDE (assosiation)

7. Näytölle tulostaminen 7.1

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

SATAKUNNAN AMMATTIKORKEAKOULU. Minna Seppi TIEDOSTOPALVELU RMI-TEKNIIKALLA

Tietorakenteet. JAVA-OHJELMOINTI Osa 5: Tietorakenteita. Sisällys. Merkkijonot (String) Luokka String. Metodeja (public)

RINNAKKAINEN OHJELMOINTI A,

Java-kielen perusteita

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

TIETORAKENTEET JA ALGORITMIT

RMI TOIMIVAA ETÄPROSEDUURIOHJELMINTIA

Ohjelmoinnin peruskurssien laaja oppimäärä

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Tietorakenneluokkia 2: HashMap, TreeMap

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista

11. Javan valintarakenteet 11.1

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

Sisällys. Metodien kuormittaminen. Luokkametodit ja -attribuutit. Rakentajat. Metodien ja muun luokan sisällön järjestäminen. 6.2

Sisältö. Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 6.2

8. Näppäimistöltä lukeminen 8.1

Transkriptio:

HOJ RMI = Remote Method Invocation Ville Leppänen HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.1/37

Missä mennään... 1. Johdanto (1h) 2. Säikeet (2h) 3. Samanaikaisuudesta (2h) 4. Hajautetuista sovelluksista (1h) 5. Soketit (3h) 6. RMI ja J2EE (2h) 7. RPC (1h) 8. WWW-sovellustekniikoista (2h) 9. Pilvialustat (4h) 10. Haja-aiheita (2h) 99. Kertausluento (2h) + 1h pelivaraa HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.2/37

Remote Method Invocation: Yleistä 1/2 Palvelinsovellus kuuntelee yhteydenottoja; yhteydenotto = metodin kutsu ja suorittaminen palvelimessa. Asiakas kutsuu palvelinsovellusta suorittamaan jokin etäolion jotain tiettyä metodia (parametrit). Parametrit: tietoa asiakkaalta palvelimelle. Tulos: tietoa palvelimelta asiakkaalle. Tietoa välitetään Javan olioina! Palvelin- & asiakassovellus: Java-ohjelmia. Yleisesti: useita palvelimia ja asiakkaita. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.3/37

RMI: Yleistä 2/2 Etäolio (server object): palvelimessa oleva olio. Paikallinen olio (client object): asiakassovelluksessa. Edustajaolio (stub): asiakkaalla on olio, joka edustaa palvelimessa olevaa etäoliota. Tukee turvallisuusominaisuuksia ja roskien keruuta (yms). Asiakkaan ja palvelimen roolit eivät kiinteitä: osapuoli voi olla molemmissa rooleissa. Paketit java.rmi (asiakas); java.rmi.server (palvelin); java.rmi.registry (rekisteri: nimiä palvelimen olioille);... HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.4/37

RMI:n kulisseissa tapahtuu (asiakas) (palvelin) rekisteri palvelinohj. asiakasohj. etäolio luonti etäoliota vastaava edustajaolio rekisteristä etäolion rekisteröinti metodin kutsu paikalliselle ohjelmalle edustajaolio kutsun + param. ohjaus eteenpäin tulosten välittäminen edustajaoliolle kutsun suoritus edustajaolion olion kutsuja odottava säie tulokset takaisin HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.5/37

RMI: mitä kutsussa tapahtuu? Asiakas tekee kutsun edustajaolion välityksellä. Edustajaolio muodostaa etäkutsun: Etäolion tunniste Etäolion kutsuttava metodi Parametrien koodaus (marshalling) jonka se lähettää palvelimelle. Palvelin vastaanottaa tiedot, purkaa ne ja kutsuu etäolion metodia. Tuloksen palvelin lähettää koodattuna takaisin asiakassovellukselle, joka ottaa vastaan ja purkaa koodauksen. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.6/37

Parametrien koodaus Paikalliset oliot: syväkopiona Serializable:n avulla. Transitiivinen sulkeuma. Primitiiviarvot: kopioimalla. Etäoliot: viittauksena. Olion sarjallistamisen yhteyteen koodataan myös tieto luokasta: nimi, sormenjälki, yms. Toisessa päässä määrittelyt ladataan suoritusympäristöön ja tarkistetaan, että sillä tuntettavilla vastaavilla luokilla on sama sormenjälki. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.7/37

Etäolioon liittyvät luokat 1/3 Asiakassovelluksessa etäolioihin ei viitata suoraan niihin viitataan rajapinnan avulla. interface Noppa extends Remote {... metodeja } Pitää aina periä Remote:sta. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.8/37

Etäolioon liittyvät luokat 2/3 Etäolio toteuttaa kyseisen rajapinnan ja perii luokasta UnicastRemoteObject (yleisemmin: RemoteServer). public class NoppaToteutus extends UnicastRemoteObject implements Noppa {... toteutus... } HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.9/37

Etäolioon liittyvät luokat 3/3 Palvelinsovellus: itsenäinen luokka, joka luo ja nimeää etäoliot. Asiakassovellus: itsenäinen luokka, joka etäolion verkkonimen perusteella luo edustaolion, jonka avulla se toteuttaa RMI-kutsut. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.10/37

Noppa.java import java.rmi. ; public interface Noppa extends Remote { public void setseed(long l) throws RemoteException; public void setmax(int m) throws RemoteException; public void setmin(int m) throws RemoteException; public int getnext() throws RemoteException; } // interface Noppa HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.11/37

NoppaToteutus.java import java.rmi. ; import java.util. ; import java.rmi.server. ; public class NoppaToteutus extends UnicastRemoteObject implements Noppa { private Random gen = new Random(); private int min, max, diff; public NoppaToteutus() throws RemoteException { min = 1; max = 6; diff = 6; } public NoppaToteutus(int mi, int ma) throws RemoteException { min = mi; max = ma; diff = ma-mi+1; } public void setseed(long l) throws RemoteException { gen.setseed(l); } public void setmax(int m) throws RemoteException { max = m; diff = max - min; } public void setmin(int m) throws RemoteException { min = m; diff = max - min; } public int getnext() throws RemoteException { return Math.abs(gen.nextInt()%diff) + min; } } // class NoppaToteutus HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.12/37

NoppaServer.java import java.rmi. ; import java.rmi.server. ; public class NoppaServer { public static void main(string[] q) { try { NoppaToteutus noppa = new NoppaToteutus(); Naming.rebind("noppa", noppa); } catch (Exception e) { System.out.println("Error: " + e); } } // main } // class NoppaServer HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.13/37

NoppaClient.java import java.rmi. ; import java.rmi.server. ; public class NoppaClient { public static void main(string[] q) { // q[0] = RMI-registerikoneen nimi if (q.length 1) { System.out.println("Usage: NoppaClient <serverhost>"); System.exit(0); } System.setSecurityManager(new RMISecurityManager()); String osoite = "rmi://" + q[0] + "/noppa"; try { Noppa n = (Noppa)Naming.lookup(osoite); for (int i=0; i<20; i++) System.out.print(" " + n.getnext()); System.out.println(" "); } catch (Exception e) { System.out.println("Error: " + e); } } // main HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.14/37

Käyttäminen javac Noppa*.java (käännetään kaikki) rmic -v1.2 NoppaToteutus (luodaan edustaolio NoppaToteutus_Stub) start rmiregistry (Windows) rmiregistry & (Unix) (käynnistetään rmi-rekisteripalvelin; portti 1099) start java NoppaServer (Windows) java NoppaServer & (Unix) (käynnistetään Noppa-palvelinsovellus taustalle; registeröityy edelliselle) java -Djava.security.policy=Noppa.policy NoppaClient (käynnistetään sovellus määrätyllä turv.määrittelyillä) HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.15/37

Oikeudet Noppa.policy: grant { permission java.net.socketpermission "*:1024-65535", "connect"; }; HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.16/37

Luokkia RMISecurityManager Turvallisuusmanageri, joka kontrolloi suoritettavan koodin (stub) lataamista. Vain konstruktori. Ei appleteille. Asiakassovellukseen. Remote Rajapinta; ei metodeja. UnicastRemoteObject Luokka; mahdollistaa TCP:n päällä tapahtuvan etäkäytön. Kaikkiin metodeihin throws RemoteException. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.17/37

Luokkia: Naming Naming: Sen avulla toteutetaan olioiden nimeäminen (rekiströinti) URL:n tapaan. "rmi://kone.portti/nimi". static void bind(string, Remote) sitoo nimen olioon (ei saa olla jo määr.) static void rebind(string, Remote) sitoo nimen olioon static void unbind(string) tekee nimestä määrittelemättömän static Remote lookup(string) palauttaa nimeä vastaavan edustaolion static String[] list(string) rekisterissä olevat tunnisteet HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.18/37

Luokka RemoteException 1/2 RMI-kutsu edustaolion välityksellä voi päättyä poikkeukseen. Poikkeus syntyy palvelimessa ja se välitetään RMI:n avulla asiakkaalle. Tällaisia poikkeuksia varten luokka RemoteException. Useita aliluokkia (n. 10). Jokaisessa rajapinnasta Remote laajennetussa rajapinnassa pitää kaikissa metodeissa olla throws RemoteException. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.19/37

Luokka RemoteException 2/2 Syy: verkko-operaatiot voivat aihettaa poikkeuksen, kun etäoliota käytetään edustaolion välityksellä. Poikkeus pitää olla myös rajanpinnan toteuttavissa konstruktoreissa ja toteutettavissa metodeissa mutta ei muissa metodeissa. Lisäksi voidaan vapaasti määritellä muitakin poikkeuksia, jotka kulkeutuvat RMI:n välityksellä. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.20/37

NumeroPeli.java import java.rmi. ; interface NumeroPeli extends Remote { public boolean lisääpelaaja(numeropelaaja p) throws RemoteException; public int montakopelaajaa() throws RemoteException; public NumeroPelaaja annapelaaja(int nro) throws RemoteException; public boolean sovellasiirtoa(numeropelaaja p, boolean alusta) throws RemoteException; public int annapisteet(numeropelaaja p) throws RemoteException; public String näytäluvut() throws RemoteException; public int[] annaluvut() throws RemoteException; public boolean peliohi() throws RemoteException; } // interface NumeroPeli HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.21/37

NumeroPelaaja.java import java.rmi. ; interface NumeroPelaaja extends Remote { public String annanimi() throws RemoteException; public void teesiirto() throws RemoteException; public boolean issimilar(numeropelaaja p) throws RemoteException; public void tiedoita(string s) throws RemoteException; public void saavuoron() throws RemoteException; public void lopeta() throws RemoteException; } // interface NumeroPelaaja HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.22/37

NumeroPeliToteutus.java 1/7 import java.rmi. ; import java.rmi.server. ; import java.util. ; public class NumeroPeliToteutus extends UnicastRemoteObject implements NumeroPeli { private NumeroPelaaja player1, player2; private int points1, points2; private Vector numbers; private int remaining; public NumeroPeliToteutus() throws RemoteException { player1 = null; player2 = null; } // NumeroPeliToteutus() private void alusta() { points1 = 0; points2 = 0; numbers = new Vector(); for (int i=0; i<10; i++) numbers.add(new Integer((int)(Math.random() 21) - 10)); remaining = 10; } // alusta HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.23/37

NumeroPeliToteutus.java 2/7 public boolean lisääpelaaja(numeropelaaja p) throws RemoteException { if (player1 == null) { player1 = p; return false; } else if (player2 == null) { player2 = p; alusta(); player1.tiedoita("game begins."); player2.tiedoita("game begins."); String tied = player1.annanimi() + "versus " + player2.annanimi(); player1.tiedoita(tied); player2.tiedoita(tied); player1.tiedoita("numbers " + näytäluvut()); player2.tiedoita("numbers " + näytäluvut()); player2.saavuoron(); return true; } else throw new RemoteException("Game full!"); } // lisääpelaaja HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.24/37

NumeroPeliToteutus.java 3/7 public int montakopelaajaa() throws RemoteException { if (player2 null) return 2; if (player1 null) return 1; return 0; } // montakopelaajaa public NumeroPelaaja annapelaaja(int nro) throws RemoteException { if ((nro > 2) (nro < 1)) return null; if (nro == 1) return player1; else return player2; } // annapelaaja HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.25/37

NumeroPeliToteutus.java 4/7 public boolean sovellasiirtoa(numeropelaaja p, boolean alusta) throws RemoteException { if ((!player1.issimilar(p)) && (!player2.issimilar(p))) throw new RemoteException("Illegal player!"); if (remaining == 0) throw new RemoteException("Illegal move!"); int n = 0; String tied = " "; if (alusta) { n = ((Integer)numbers.remove(0)).intValue(); tied = "first"; } else { n = ((Integer)numbers.remove(numbers.size()-1)).intValue(); tied = "last"; } tied = "took the " + tied + "number " + n + "."; if (player1.issimilar(p)) { points1 += n; tied = "Player 1 " + tied; } else { points2 += n; tied = "Player 2 " + tied;} player1.tiedoita(tied); player2.tiedoita(tied); remaining--; HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.26/37

NumeroPeliToteutus.java 5/7 if (remaining == 0) { pelinlopetus(p); player1 = player2 = null; return true; } else { if (player1.issimilar(p)) player2.saavuoron(); if (player2.issimilar(p)) player1.saavuoron(); return false; } } // sovellasiirtoa HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.27/37

NumeroPeliToteutus.java 6/7 private void pelinlopetus(numeropelaaja p)throws RemoteException { String tied = "Player 1 score = " + points1; player1.tiedoita(tied); player2.tiedoita(tied); tied = "Player 2 score = " + points2; player1.tiedoita(tied); player2.tiedoita(tied); if (points1 < points2) tied = "Player 2 has won!"; else if (points1 > points2) tied = "Player 1 has won!"; else tied = "Game ended up to a draw."; player1.tiedoita(tied); player2.tiedoita(tied); if (player2.issimilar(p)) player1.lopeta(); else player2.lopeta(); // Toista pelaajaa käsketään lopettaa toisella // tapaa, koska sillä on vielä kutsu auki. } // pelinlopetus public int annapisteet(numeropelaaja p) throws RemoteException { if (player1.issimilar(p)) return points1; if (player2.issimilar(p)) return points2; throw new RemoteException("Player not playing"); HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.28/37 } // annapisteet

NumeroPeliToteutus.java 7/7 public String näytäluvut() throws RemoteException { String t = " "; for (int i=0; i<remaining; i++) t += ((Integer)numbers.get(i)).intValue() + ; return t; } // näytäluvut public int[] annaluvut() throws RemoteException { int[] q = new int[remaining]; for (int i=0; i<remaining; i++) q[i] = ((Integer)numbers.get(i)).intValue(); return q; } // annaluvut public boolean peliohi() throws RemoteException { return (remaining == 0); } public static void main(string[] q) throws Exception { Naming.rebind("NumeroPeliPalvelin", new NumeroPeliToteutus()); } // main } // class NumeroPeli HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.29/37

NumeroPelaajaToteutus.java 1/3 import java.rmi. ; import java.rmi.server. ; public class NumeroPelaajaToteutus extends UnicastRemoteObject implements NumeroPelaaja, Runnable { private NumeroPeli game; private String name; private boolean ismyturn; private boolean stillplaying; public static void main(string[] args) throws Exception { if (args.length < 2) { System.out.println("Paramters: <server> <player name>"); System.exit(0); } String palvelin = args[0].trim(); String pelaajannimi = args[1].trim(); NumeroPeli peli = (NumeroPeli)Naming.lookup(palvelin); new NumeroPelaajaToteutus(peli, pelaajannimi); } // main HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.30/37

NumeroPelaajaToteutus.java 2/3 public NumeroPelaajaToteutus(NumeroPeli peli, String nimi) throws RemoteException { game = peli; name = nimi; stillplaying = true; ismyturn = false; game.lisääpelaaja(this); new Thread(this).start(); } // NumeroPelaajaToteutus public String annanimi() throws RemoteException { return name; } public void teesiirto() throws RemoteException { boolean alusta = (Math.random() < 0.5); stillplaying =!(game.sovellasiirtoa(this, alusta)); } // teesiirto public boolean issimilar(numeropelaaja p) throws RemoteException { // Jos edustaolioita vertaa suoraan == :lla, // niin tulos voi olla "väärä", koska viime // kädessä halutaan verrata vastaavia olioita. return (this.name.equals(p.annanimi())); } // issimilar HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.31/37

NumeroPelaajaToteutus.java 3/3 public void tiedoita(string s) throws RemoteException { { System.out.println("Server: " + s); } public void saavuoron() throws RemoteException { { ismyturn = true; } public void run() { while (stillplaying) { if (ismyturn) { ismyturn = false; try { teesiirto(); } catch (Exception e) { throw new Error(e.toString()); } } try { Thread.sleep(300); } catch (InterruptedException e) { } } // while System.out.println("Game over!"); System.exit(0); } // run public void lopeta() throws RemoteException { stillplaying = false; // kills the thread } // lopeta } // class NumeroPelaajaToteutus HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.32/37

Sovellusten keskustelusta Kaksi palvelinsovellusta voi keskustella keskenään. RMI: metodin kutsu = vaikuttamisen yhteydessä pitää huolehtia, ettei tule avoimien kutsujen sykliä. Tavallaan kutsut tarkoittavat vuoron siirtämistä toiselle. Molemmat osapuolet aktiivisia: ei syklejä, jos metodin kutsu tarkoittaa palvelupyynnön välittämistä. Riittää kun vain toiseen suuntaan palvelupyyntöjä! Ratkaisu: molemmilla itsenäinen säie & RMI-kutsut ainakin toiseen suuntaan palvelupyyntöjä. Paljon säikeitä: main, itsenäinen säie (+ ilm. Remote-oliota varten syntyy oma säie). HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.33/37

Pelipöytä-sovellukset Tieto pelin tilasta palvelinsovelluksella. Palvelinsovellus kontrolloi pelin etenemistä. Asiakkaat myös etäolioita. Palvelimella asiakkaista edustaolio. Palvelin voi olla passiivinen: peli etenee vain pelaajien toimenpiteiden seurauksena. Pitää välttää avointen kutsujen syklit: palvelin välittää palvelupyyntöjä (ei kutsu suoraan peliä ohjaavia asiakkaan metodeja). Lopettaminen hankalaa: yleensä asiakkaan kutsun seurauksena. Palvelin tekee lopettamisen. Avoin etäolio pitää käsitellä toisin. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.34/37

Turvallisuudesta Mahdollista kryptata RMI-liikenne (voidaan vaihtaa RMI:n käyttämät tavalliset soketit SSL-soketeiksi). Palvelimen puolella ei ole tukea sille, että rajoitettaisiin oikeutta tehdä kutsu edustaolion kautta (miten palvelin tietää kuka sitä kutsuu? edustaolio voidaan välittää eteenpäin...). Palvelimeen voidaan tehdä login-osuus, jonka jälkeen saa varsinaisen etäolion palveluiden käyttämiseksi. Kyseinen olio voi olla erilainen eli käyttäjille. Palvelimen pitää varautua siihen, että asiakas häiriköi. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.35/37

Jakamisesta ja lukoista RMI ei varsinaisesti tunne lukkoja, mutta... RMI:n yhteydessä on mahdollista soveltaa lukkoja palvelipäässä. RMI-palvelin on monisäikeinen (kutakin samanaikaista kutsua toteuttaa eri säie). Määritellään kriittiset etäolion operaatiot sychronized-suojatuiksi. Suojaa etäoliokutsujen kautta tapahtuvaa samanaikaista käyttöä (sekä muuta palvelimessa etäolioon tapahtuvaa käyttöä). Asiakas ei siis suoraan saa lukkoa etäolioon (vaan sen edustaja etäkutsua suorittava säie palvelimessa). wait()/notify() hankalia mutta mahdollisia lähinnä vain estetään samanaikainen jaetun datan käyttö. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.36/37

Yhteenveto RMI = Remote Method Invocation. Etäolio + edustaolio. Kutsulla saadaan aikaan tiedon siirto molempiin suuntiin voidaan välittää olioita kopioimatta. Edustaolioiden == eri kuin etäolioiden ==!! Kutsuja aktiivinen; kutsuttava passiivinen. Pitää varoa avoimien kutsuketjujen sykliä. Palvelin vs useita asiakkaita: helppo. Palvelin & palvelin: vaikeampi. Toteutettu säikeillä ja soketeilla. HOJ, c Ville Leppänen, IT, Turun yliopisto, 2012 p.37/37