Realisierung verteilter Anwendungen: Teil 2 Ralf Möller, FH Wedel Inhalt heute: Kommunikation über Sockets Java Remote Method Invocation, RMI Lernziele: Verständnis eines Basisdienstes: Sockets (in Java) Grundlage von „Middleware“-Architekturen: Überblick über RMI Verteilung und Kommunikation Kommunikationsprotokoll Beispiel: TCP/IP Schicht 4 (bzw. 3) des ISO/OSI Referenzmodells Transport von Informationen über ein Netzwerk Zwei Arten: TCP UDP Application Presentation Session Transport Network Data link Physical email s erv er Desktop computers print and other servers Web server Local area netw ork email s erv er File s erv er print other servers the rest of the Internet router/firew all TCP Client Server Application Application Presentation Presentation Session Transport Session Request Input Stream Transport Output Stream Result UDP Client Server Application Application Presentation Presentation Session Request-Datagrams Transport Session Transport Result Datagrams Adressierung und Abstraktion (in Java) Adressierung eines Knotens (Computer) IP-Adresse (z.B. 134.100.12.135) oder Name Port (z.B. 8088) Namensdienste: DNS socket any port agreed port socket message client server other ports Internet address = 138.37.94.248 Internet address = 138.37.88.249 Internet name = vodka Sockets (Server-Seite) import java.net.*; int port = 1234; ServerSocket server = new ServerSocket(port); while (true) { System.out.println("Waiting for client ..."); Socket client = server.accept(); System.out.println("Client " + client.getInetAddress() + " connected."); } Sockets (Client-Seite) import java.net.*; Socket server = new Socket("vodka", 1234); System.out.println("Connected to " + server.getInetAddress()); Eine Abstraktion: Ströme (streams) und Filter By te Byte te By OutputStream Bo o l e an Integer ing S tr Ohne Filter DataOutputStream InputStream BufferedOuputStream InputStream te By Byte B y te BufferedInputStream OutputStream DataInputStream ing St r Integer Bo o l ea n Mit Filter: Datenaufbereitung + Pufferung TimeServer import java.net.*, java.io.*, java.util.*; public class TimeServer { Public static void main(String args[]) throws IOException { int port = 1234; ServerSocket server = new ServerSocket(port); while (true) { System.out.println("Wait for client ... "); Socket client = server.accept(); OutputStream out = client.getOutputStream(); Date date = new Date; byte b[] = date.toString().getBytes(); out.write(b) } } } TimeClient import java.net.*, java.io.*; public class TimeClient { Public static void main(String args[]) throws IOException { int port = 1234; Socket server = new Socket("vodka", 1234); InputStream in = server.getInputStream(); byte b[] = new byte[100]; int num = in.read(b); String date = new String(b); ... } } } TimeServer mit Filter DataOutputStream out = new DataOutputStream( new BufferedOutputStream( client.getOutputStream())); Date = new Date; out.writeUTF(date.toString()); out.flush(); UTF-8: Übertragungsformat für Zeichenketten (Unicode) TimeClient mit Filter DataInputStream in = new DataInputStream( new BufferedInputStream( server.getInputStream())); System.out.println("Server said: " + in.readUTF()); MulticastSockets InetAddress group; MulticastSocket socket; group = InetAddress.getByName("226.1.3.5"); byte[] buf = new byte[1000] socket.joinGroup(group); ... DatagramPacket dg = new DatagramPacket(buf, buf.length(), group, port); socket.receive(dg); String message = new String(dg.getData()); socket.send(dg); Lehnen wir uns zurück Ist durch das Design mit „Sockets“ und „Threads“ Transparenz gegeben? Zugriffstransparenz (lokal vs. global) Ortstransparenz Nebenläufigkeitstransparenz Replikationstransparenz Fehlertransparenz Migrationstransparenz Performanz- und Skalierungstransparenz Ein BeiSpiel: Simple Baseball public class Bat { public void play (Ball ball) { ball.hit(); } public static void main (String args[]) { Ball ball = new Ball(); Bat bat = new Bat(); bat.play(ball) } } public class Ball { public void hit() { System.out.println("Ball has been hit.") } } $ java Bat Ball has been hit. Transparenz bei der Socket-Architektur ? + Datei vs. (entfernter) Port (Ströme) Binär, zeichenkettenbasiert, Filter für Primitivtypen - Daten(de)kodierung schwierig zu programmieren local remote invocation A B C local E invocation invocation local invocation D -> In C: Remote Procedure Call (RPC) -> In OOP: Senden von Nachrichten an entfernte Objekte -> In Java: Remote Method Invocation (RMI) remote invocation F Remote Method Invocation (RMI) Probleme: Quasi-transparenter Aufruf von Methoden von Objekten auf verschiedenen virtuellen Maschinen Referenzen auf Objekte eines Adreßraumes haben in einem anderen (entfernten) Adreßraum keine Bedeutung Speicherbereinigung (Garbage Collection) RMI – Ziele: Vereinfachung der Entwicklung zuverlässiger verteilter Anwendungen Beibehaltung des Java-Sicherheitsmodells Unterstützung von Unicast and Multicast Die Architektur von RMI Client vs. Server Server veröffentlicht Schnittstelle Registrierung vs. Lokalisierung von Servern Registratur (registry) Namensdienste Server: Konventionen bei der Programmierung Klassenstruktur java.rmi.RemoteObject java.rmi.Remote java.rmi.UnicastRemoteObject MyServerInterface extends MyServer implements Das Beispiel mit RMI: der Server (1) import java.rmi.* public interface RemoteBall extends Remote { public void hit() throws RemoteException; } Das Beispiel mit RMI: der Server (2) import java.rmi.server.*; public class Ball extends UnicastRemoteObject implements RemoteBall { public Ball() throws RemoteException { super(); } public void hit() { System.out.println("Ball has been hit."); }... Das Beispiel mit RMI: der Server (3) ... public static void main(Sting args[]) { try { Ball ball = new Ball(); Naming.rebind("Ball", ball); } catch (Exception e) { e.printStackTrace(); }}} vodka$ javac Ball.java; rmic Ball; rmirestristy; java Ball Erzeugung von Stubs und Skeletons rmic Ball(.class) Erzeugen der Klasse Ball_Stub.class ... ... und der Klasse Ball_Skel.class Stub wird auf Client-Seite benötigt Bereitstellung als File oder ... ... Nachladen über das Netz (SecurityManager) Das Beispiel mit RMI: der Client (1) import java.rmi.*; public class Bat { Interface RemoteBall.java muß beim Client vorhanden sein: Statische Stellvertreter public Ball ball; public void play(RemoteBall ball) { try { ball.hit(); } catch (RemoteException e) { System.out.println(e); } } Das Beispiel mit RMI: der Client (2) public static void main(String args[]) { Bat bat = new Bat(); try { System.setSecurityManager(new RMISecurityManager()); RemoteBall remoteBall = (RemoteBall) Naming.lookup("rmi://vodka.fh-wedel.de/Ball"); bat.play(remoteBall); } catch (Exception e) { System.out.println(e); } } } client$ java Bat Ball has been hit. Wo wird gedruckt? Das Beispiel mit RMI: der Client (2) public static void main(String args[]) { Bat bat = new Bat(); try { System.setSecurityManager(new RMISecurityManager()); RemoteBall remoteBall = (RemoteBall) Naming.lookup("rmi://vodka.fh-wedel.de/Ball"); bat.play(remoteBall); } catch (Exception e) { System.out.println(e); } } } client$ java Bat server| Ball has been hit. Nachrichten mit Parameter (1) import java.rmi.*, java.rmi.server.*; public interface RemoteBall extends Remote { public void hit(Player p) throws RemoteException; } public class Ball extends UnicastRemoteObject implements RemoteBall { public Ball() throws RemoteException { super(); } ... Nachrichten mit Parameter (2) public void hit(int n) { System.out.println("Ball has been hit by." + " player " + n); } public void hit(Player p) { System.out.println("Ball has been hit by." + p.name() + " from team " + p.team()); } } Nachrichten mit Parameter (3) public class Player { Was wäre, wenn "team" ein Objekt wäre? String name; String team; public Player(String playername, String teamname) { name = playername; team = teamname; } public String name() { return name; } public String team() { return team; } } Nachrichten mit Parameter (4) Pass-by-Value von Objektstrukturen "Kopiersemantik" Änderungen auf der Zielseite sind nicht auf der Senderseite sichtbar (und umgekehrt)! Pass-by-Reference bei entfernten Objekten (Stubs) "Zeigersemantik" Details in: Troy Brian Downing, Java RMI: Remote Method Invocation, Prentice Hall (1998). Realisierung einer Callback-Kommunikation? Server Client auch als RMIServer implementieren! Server kann dann Client über normalen Methodenaufruf kontaktieren Trennung zwischen Server und Client wird aufgehoben Verteilte Müllbeseitigung (Garbage Collection) Bei RMI wird nicht nur festgehalten, ob Referenzen auf ein Objekt vorhanden sind, sondern auch, von welcher VM aus. Feststellung, ob ein Objekt noch benötigt wird Details kommen später ... Zusammenfassung: RMI Namensverwaltung für Objektreferenzen Senden einer Nachricht (synchrone Kommunikation) RMI übernimmt Parameter- und Ergebnistransfer (Marshalling and Demarshalling) Umrechnung in externe Datenrepräsentation Wiederherstellung von Objektstrukturen In Java: Interface "serializable" RMIClassloader RMI und Heterogenität Kein Problem, solange die VM von Java verwendet wird RMI und Sicherheit Standardmäßig keine Verschlüss elung von Daten Standardmäßig keine Authentifizierung Kein Rechtesystem Jeder kann die Registratur abfragen Stubs/Skeletons können simuliert werden Keine Versionskontrolle zwischen Stub und Skeleton Bevor alle davoneilen Fortsetzung der Diskussion über Middleware ... mit dem Thema CORBA und Sprachunabhängigkeit ... beim nächsten Mal.