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.