30.03.2004 Distinguished Lectures Series im SS04 And now... now... • MDA-gestütztes Architekturmanagement im Volkswagen-Konzern: Ein Erfahrungsbericht • Dr. Frank Derichsweiler, Architekturmanagement, AUDI AG „And now for something completely different.“ • Repository für VW-konzernweites Architekturmanagement • modellbasiert über domänenspezifische MDA-Profile konfigurierbar • erstellt mit MDA als Pilot für modellbasierte Systementwicklung • Dienstag, 06.04.2004, 10:15 Uhr, Klostergasse 3 (2. OG) • Details zu diesem und weiteren Vorträgen: • www.lpz-ebusiness.de Java-Einführungskurs 1 Java-Einführungskurs YOU ARE HERE Exkurs: Threads • • • • • • • • • Bislang lief in unseren Programm immer nur ein Programmteil, nicht mehrere parallel zur gleichen Zeit. Einführung Objektorientierte Modellierung Java-Sprachkonstrukte Java-Klassenbibliothek Zeichenketten Dateien und Streams Datenstrukturen Networking • übliche Situation bei Netzwerkanwendungen jedoch: • viele Clients (z.B. Web-Browser) greifen nahezu gleichzeitig auf einen Server (z.B. www.lpz-ebusiness.de) zu • bei sequentieller Abfertigung aller Anfragen durch den Server wäre die Wartezeit für einzelne Clients zu lang ¾ Server muss mehrere Anfragen "gleichzeitig" beantworten können Exkurs: Threads • Netzwerkadressen und -verbindungen • Client/Server-Programmierung • Realisierung mit Threads („Fäden“) • Grafische Benutzungsoberflächen • Extensible Markup Language • Threads sind Programmteile, die innerhalb des Programms parallel ausgeführt werden. Java-Einführungskurs 3 Java-Einführungskurs SingleSingle- vs. MultiMulti-Threading Verwendung der Oberklasse Thread • Bisher: Single-Threaded Execution • in Java: Darstellung durch Oberklasse Thread Methode b t • eigene Threads müssen Unterklassen von Thread sein • müssen dabei die Methode run() überschreiben dort steht der Teil, der parallel ausgeführt werden soll • start() wird nicht überschrieben • ein Thread wird über den Aufruf der start()-Methode angestoßen (nicht über direkten Aufruf von run() !) • nach dem start()-Aufruf kehrt der Kontrollfluss unmittelbar in den aufrufenden Programmteil zurück, während der Thread parallel läuft • mehrfaches Aufrufen von start() führt zu mehreren parallelen Ausführungen von run() • Neu: Multi-Threading Methode c Methode c Methode a Methode b t Java-Einführungskurs 4 public class Thread implements Runnable { public void run() {...}; // überschreiben, nicht aufruf. public void start() {...}; //aufrufen,nicht überschreib. ... } Methode c Methode a 2 5 Lehrstuhl für Angewandte Telematik/e-Business Java-Einführungskurs 6 1 30.03.2004 Beispiel: ThreadThread-Programmierung YOU ARE HERE • Implementierung des als Thread auszuführenden Codes: • • • • • • • • class PrimeThread extends Thread { long minPrime; PrimeThread(long minPrime) { this.minPrime = minPrime; } public void run() { ... // auf minPrime folgende Primzahl berechnen } • Exkurs: Threads Netzwerkadressen und -verbindungen • Client/Server-Programmierung } • Instanziierung und Aufruf des Threads: PrimeThread p = new PrimeThread(143); p.start(); ... // Programm fährt direkt fort, während p.run() läuft Java-Einführungskurs Einführung Objektorientierte Modellierung Java-Sprachkonstrukte Java-Klassenbibliothek Zeichenketten Dateien und Streams Datenstrukturen Networking • Grafische Benutzungsoberflächen • Extensible Markup Language 7 Paket java. java.net Java-Einführungskurs 8 Begriffe • Ein verteiltes System ist eine Ansammlung von locker gekoppelten Prozessoren, die über ein Netzwerk verbunden sind. • Man unterscheidet zwischen lokalen und entfernten (local und remote) Ressourcen. • Auf unterer Ebene tauschen die Systeme Nachrichten (messages) aus. • Networking ist eine Stärke von Java. • Dabei sind die Prinzipien die selben wie bei Dateien und Streams. Java-Einführungskurs 9 Java-Einführungskurs 10 Identifikation von Rechnern Domain Name System • Problem: Rechner müssen eindeutig gekennzeichnet werden! • Lösung im Internet Protocol (IP): Domain Name System (DNS) und „dotted quad“ Netzwerk Netzwerk Internet Internet 123.255.28.120 123.255.29.122 ebus.informatik.uni-leipzig.de Java-Einführungskurs 11 Lehrstuhl für Angewandte Telematik/e-Business Java-Einführungskurs 12 2 30.03.2004 NetzwerkNetzwerk-Adressierung in Java Verwendung von InetAddress • DNS-Format (ebus.informatik.uni-leipzig.de) besteht aus Rechnername (ebus) und Domainname (informatik.uni-leipzig.de) • Beispiel für die Verwendung von InetAddress: import java.net.*; public class WhoAmI { public static void main(String[] args) throws Exception { if (args.length != 1) { System.err.println("Usage: WhoAmI MachineName"); System.exit(1); } InetAddress a = InetAddress.getByName(args[0]); System.out.println(a); } } • intern wird auch beim DNS-Format eine 32-bit-Zahl (entspricht dem dotted quad) gespeichert • Adresse wird von java.net.InetAddress gekapselt • InetAddress.getByName() bestimmt Adresse eines Rechners Java-Einführungskurs 13 Java-Einführungskurs 14 Local LoopbackLoopback-Adresse Clients und Server • Hinweis: Beispielprogramm funktioniert nur, wenn der Rechner mit dem Internet verbunden ist, da die Namensauflösung den DNS-Server des Netzwerks nutzt • Beim Networking nehmen beteiligte Rechner typischerweise zwei Rollen ein: Client und Server • Server stellen Dienste bereit • zum Testen ohne Netzwerkverbindung kann per „local loopback“ der eigene Rechner adressiert werden • Clients rufen Dienste ab • Name localhost oder IP-Adressse 127.0.0.1 Clients • InetAddress addr = InetAddress.getByName(null); • InetAddress addr = InetAddress.getByName("localhost"); • InetAddress addr = InetAddress.getByName(127.0.0.1); Java-Einführungskurs Server • Clients und Server sind Programme • mehrere Clients und/oder Server können auf dem gleichen Rechner (dem gleichen Gerät, "Host" genannt) laufen 15 Java-Einführungskurs 16 Ports Sockets • IP-Adressen identifizieren Rechner • mehrere Clients können zur selben Zeit mit einem Port eines Servers verbunden sein • Verbindungen werden über Sockets identifiziert • auf einem Rechner (Host) können aber mehrere Server laufen (z.B. für Mail, Web, Telnet etc.) ¾ IP-Adresse reicht zur Adressierung eines Servers nicht aus Client • zweites Adressierungsprinzip: jeder Server wird über einen bestimmten Port angesprochen Host-Rechner Stream • Port wird durch Nummer gekennzeichnet, z.B. 80 für Webserver Server Port Client Stream • Portnummer kann auch an die IP-Adresse gehängt werden: 139.18.40.1:80 Socket Java-Einführungskurs 17 Lehrstuhl für Angewandte Telematik/e-Business Java-Einführungskurs 18 3 30.03.2004 Verwendung von ClientClient-Sockets Funktion eines einfachen Clients • Kernfunktionen eines Clients: • Szenario: Auf Port 5155 unseres Rechners läuft ein Server, der bei Verbindungsaufbau eine Textzeile mit der aktuellen Uhrzeit überträgt. • Was muss ein Client tun, um auf diesen Dienst zuzugreifen? • Verbindung zu einem bestimmten Port auf einem bestimmten Host aufbauen Socket socket = new Socket(host, port); • Socket enthält individuelle Verbindung des Clients zum Host • Verbindung zu Port 5155 auf localhost aufbauen • Streams zum Datentransfer über die Verbindung "besorgen" InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); • wir erhalten ein Socket für diese Verbindung • Stream zum Lesen von Daten aus dem Socket besorgen • wir erhalten einen InputStream, der mit dem Socket verbunden ist • einen BufferedReader an den InputStream hängen • damit können wir nicht nur Bytes, sondern ganze Textzeilen lesen • Datenaustausch über die Streams nun wie bei Dateien! • eine Zeile aus dem BufferedReader lesen • Zeile ausgeben - fertig! Java-Einführungskurs 19 Beispiel: TimeTime-ofof-DayDay-Client generischer Teil Java-Einführungskurs 20 Funktion eines einfachen Servers • Szenario: Auf Port 5155 unseres Rechners läuft ein Server, der bei Verbindungsaufbau eine Textzeile mit der aktuellen Uhrzeit überträgt. • Was muss der Server tun, um diesen Dienst anzubieten? • auf Port 5155 ein Socket für Verbindungsanfragen öffnen public class Client { public void receiveTime() throws Exception { Socket socket = new Socket("localhost", 5155); InputStream in = socket.getInputStream(); BufferedReader br = new BufferedReader( new InputStreamReader(in)); • wir erhalten einmalig ein sog. Server-Socket, das immer offen bleibt • am Server-Socket nach Verbindungsanfragen lauschen System.out.println(br.readLine()); socket.close(); • für jede Verbindung erhalten wir ein individuelles Verbindungssocket } • Stream zum Senden von Daten an das V.Socket besorgen public static void main(String args[]) throws Exception { Client client = new Client(); client.receiveTime(); "Don't try this at home" } schlechter Stil, besser • einen PrintWriter an den OutputStream hängen • wir erhalten einen OutputStream, der mit dem VSocket verbunden ist } • damit können wir nicht nur Bytes, sondern auch Textzeilen schreiben • eine Zeile in den PrintWriter schreiben • die das Datum enthält - fertig! vernünftig behandeln! Java-Einführungskurs 21 Verwendung von ServerServer-Sockets 22 Beispiel: TimeTime-ofof-DayDay-Server • Kernfunktionen eines Servers: • einmal bei der Initialisierung: • Server-Socket zum Lauschen an einem Port öffnen public class Server { private ServerSocket listener; public Server() throws Exception { listener = new ServerSocket(5155); // Portnummer } ServerSocket listener = new ServerSocket(port); • dieses Socket ist erster Kontaktpunkt für eingehende Verbindungen public void serve() throws Exception { Socket socket; OutputStream out; PrintWriter pw; while (true) { // Endlosschleife socket = listener.accept(); out = socket.getOutputStream(); pw = new PrintWriter(out, true); // true: auto-flush pw.println(new java.util.Date().toString()); socket.close(); } } • mehrfach während des Betriebs: • für jede eingehende Verbindung individuelles Socket öffnen Socket socket = listener.accept(); • dieses Socket enthält indiv. Verbindung des Hosts zu diesem Client • Streams zum Datentransfer über die Verbindung "besorgen" InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); public static void main(String args[]) throws Exception { Server server = new Server(); server.serve(); } • Datenaustausch über die Streams nun wie bei Dateien! Java-Einführungskurs generischer Teil Java-Einführungskurs 23 Lehrstuhl für Angewandte Telematik/e-Business } Java-Einführungskurs 24 4 30.03.2004 Motivation: MultiMulti-Threading Funktion eines multimulti-threaded Servers • beim Time-of-Day-Server ist jede Anfrage schnell bearbeitet • Aufteilung des Programms auf zwei Klassen: • nur das aktuelle Datum ausgeben und Verbindung sofort schließen • Server lauscht, nimmt Anfragen an und startet Threads • falls die Bearbeitung von Anfragen länger dauern würde • könnte es passieren, dass Anfragen von anderen Clients bereits eingehen, während der Server noch die erste Anfrage bearbeitet • die anderen Clients müssten in diesem Fall warten, bis alle vorherigen Anfragen abgearbeitet wurden und sie an der Reihe sind • bei hoher Anfragefrequenz/langer Bearbeitungszeit nicht akzeptabel • Programmfortsetzung unmittelbar mit Lauschen • Bearbeitung in run()-Methode parallel zu Server/anderen Threads • run() nimmt aber keine Parameter an und gibt nichts (void) zurück • schnellere Antwortzeiten, bessere Auslastung der Systemressourcen 25 Beispiel: Threaded TimeTime-ofof-DayDay-Server ¾ benötigte Werte und Kanäle für Datenrückgabe müssen schon bei der Instanziierung des Handlers im Konstruktor übergeben werden! Java-Einführungskurs public class Handler extends Thread { private Socket socket; public Handler(Socket socket) { this.socket = socket; } public void serve() throws Exception { Socket socket; while (true) { socket = listener.accept(); Handler handler = new Handler(socket); handler.start(); // sorgt für Aufruf von handler.run() } } public void run() { OutputStream out; PrintWriter pw; try { out = socket.getOutputStream(); pw = new PrintWriter(out, true); pw.println(new java.util.Date().toString()); socket.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String args[]) throws Exception { Server server = new Server(); server.serve(); } } } 27 Java-Einführungskurs Bemerkungen zur Funktionsweise Start von Server und Client • Server besteht aus zwei Klassen: Handler und Server • Server enthält die main()-Methode und erzeugt im Konstruktur ein ServerSocket • Start des Servers mittels java Server 28 • (Abbruch mit STRG+C) • in einer Endlosschleife wartet der Server durch Lauschen am ServerSocket auf das Eingehen einer Verbindung • Start des Clients mittels java Client • • • • in diesem Fall erzeugt er jedes Mal eine Handler-Instanz danach ruft er die Methode start() dieser Instanz auf Handler ist Thread-Klasse ihre run()-Methode wird einmal durchlaufen und erzeugt die Ausgabe; danach terminiert der Thread • parallel dazu läuft der Server weiter und erzeugt und startet u.U. bereits weitere Threads Java-Einführungskurs 26 Beispiel: Threaded TimeTime-ofof-DayDay-Server public class Server { private ServerSocket listener; public Server() throws Exception { listener = new ServerSocket(5155); } Java-Einführungskurs auf Server-Socket lauschen Anfragen annehmen und Verbindungs-Socket besorgen für jede neue Anfrage einen Handler-Thread instanziieren und start()-Methode des Threads aufrufen • Handler sind Threads, die Anfragen bearbeiten • Lösung: Server bearbeitet die Anfragen in einzelnen Threads, die parallel zueinander laufen Java-Einführungskurs • • • • 29 Lehrstuhl für Angewandte Telematik/e-Business • oder Abfrage des Servers mit telnet localhost 5155 Java-Einführungskurs 30 5 30.03.2004 Anwendungsbeispiel: ChatChat-System Probleme bei Parallelausführung • ein Chat-Server hat Verbindungen zu mehreren Clients • jede Eingabe auf einem Client wird vom Server empfangen und an alle Clients weitergesandt (Broadcast) • Aber: Was passiert, wenn ein Client den Chat verlässt, während gerade die Ausgabeliste abgearbeitet wird? • Er müsste während der Listen-Abarbeitung aus der Liste gestrichen werden. • Das kann zu Problemen führen, wenn gerade während des Löschvorgangs auf das betreffende Element zugegriffen werden soll und Referenzen evtl. auf null zeigen. • um Nachrichten an alle Clients zu schicken, müssen wir auf dem Server eine Liste der verbundenen Clients verwalten • dann können wir einfach durch die Liste gehen und eingehende Nachrichten an alle Clients darin ausgeben • neu verbundene Clients werden in die Liste eingetragen • Clients, die den Chat verlassen, werden aus Liste entfernt Java-Einführungskurs 31 • Auch wenn Threads parallel laufen, sollen bestimmte Operationen u.U. nicht parallel ausgeführt werden • Hier: Das Streichen des Clients aus der Liste muss eben warten, bis der Broadcast zu Ende ist. Java-Einführungskurs Verhinderung paralleler Ausführung ServerServer-Klasse ChatServer • In Java ist es möglich, dafür zu sorgen, dass trotz parallelen Ablaufs von Threads bestimmte Methoden nicht gleichzeitig ausgeführt werden. import java.io.*; import java.net.*; import java.util.*; public class ChatServer { private static LinkedList clientList = new LinkedList(); private static int id = 0; • Diese werden durch das Schlüsselwort synchronized gekennzeichnet. public static void main(String[] args) throws IOException { new ChatServer(8190); // Portnummer des Servers } • Wird eine synchronized-Methode eines Objekts aufgerufen, während eine andere synchronized-Methode noch läuft, muss die neue warten, bis die erste fertig ist. • (Wer's genau wissen will: Java verwendet pro Objekt ein Lock, das sich in vielen Fällen wie ein Monitor verhält.) Java-Einführungskurs 32 // Methoden auf folgenden beiden Folien: public ChatServer(int port) throws IOException {...} synchronized static void broadcast( String message, String name) throws IOException {...} synchronized static void remove(Socket s) {...} } 33 Java-Einführungskurs ServerServer-Klasse ChatServer ServerServer-Klasse ChatServer • Konstruktor und lauschende Endlosschleife • Nachricht an alle Clients senden 34 synchronized static void broadcast( String message, String name) throws IOException { Socket socket; PrintWriter pw; public ChatServer(int port) throws IOException { ServerSocket listener = new ServerSocket(port); Socket socket; while(true) { socket = listener.accept(); new ChatHandler(socket).start(); clientList.add(socket); id++; } } Iterator list = clientList.iterator(); while (list.hasNext()) { socket = (Socket) list.next(); pw = new PrintWriter(socket.getOutputStream(),true); pw.println(name + ": " + message); } } • Client aus der Liste streichen synchronized static void remove(Socket socket) { clientList.remove(socket); id--; } Java-Einführungskurs 35 Lehrstuhl für Angewandte Telematik/e-Business Java-Einführungskurs 36 6 30.03.2004 ServerServer-Threadklasse ChatHandler ServerServer-Threadklasse ChatHandler • Für jeden verbundenen Client wird ein ChatHandlerThread erzeugt, der Eingaben von ihm entgegennimmt. • In Endlosschleife Textzeilen vom betreffenden Client lesen und diese zum Broadcast an den Server übergeben public void run() { BufferedReader br; String s; try { br = new BufferedReader( new InputStreamReader( socket.getInputStream())); while (true) { s = br.readLine().trim(); ChatServer.broadcast(s, "User"); } // toClient.close(); } catch (Exception e) { e.printStackTrace(); } } import java.io.*; import java.net.*; public class ChatHandler extends Thread { private Socket socket; public ChatHandler(Socket socket) { this.socket = socket; } public void run() {...} // siehe nächste Folie } Java-Einführungskurs 37 Java-Einführungskurs ...und der ChatChat-Client? Hinweise zur Übungsbearbeitung • Client-Verbindung zunächst mit telnet localhost 8190 • wichtig beim Chatten im Pool: • Vorschau: grafische Oberfläche ist Thema der nächsten Übungen 38 • erst eigene IP-Adresse bestimmen (vgl. Ü7.1) und diese statt localhost verwenden • wenn mehrere Chat-Server auf demselben Rechner laufen sollen, unterschiedliche Ports (>1024) statt 8190 verwenden! • bei Arbeit auf im Pool: z.B. Portnr. = 8100 + Rechnernummer • bei Zugriff auf userv1 von außen: z.B. Portnr. = 8200 + letzte zwei Ziffern der Matrikelnummer • Rien ne va plus? • Clients und Server kann man (meist) mit Ctrl-C abbrechen • Wenn der Client hängt, hilft es auch, den Server abzubrechen Java-Einführungskurs 39 Java-Einführungskurs 40 Zusammenfasssung • Threads • parallele ("nebenläufige") Ausführung von Programmteilen • implementiert in run-Methode von Unterklassen von Thread • Netzwerkadressen und -verbindungen • IP-Adressen zur Adressierung von Rechnern (Hosts) • Ports zur Adressierung von Servern auf einem Host • Sockets zur Adressierung von indiv. Verbindungen mit einem Server • Grundprinzip der Client und Server-Programmierung • Verbindung über Socket aufbauen • auf Clients: bei Verbindung mit Host/Port ein Socket öffnen • auf Servern: zunächst Server-Socket öffnen und darauf lauschen; dann beim Annehmen von Anfragen Verbindungssocket öffnen • Ein- und Ausgabe-Streams für das Socket besorgen • Daten wie gewohnt über die Streams übertragen Java-Einführungskurs 41 Lehrstuhl für Angewandte Telematik/e-Business 7