FHZ Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K37 Sockets K37 Sockets • Inhalt 1. Client-Sockets 1. Adressierung 2. Einfache Verbindung 3. Lesen/Schreiben 2. Server-Sockets 1. Grundlagen 2. Verbindungsaufbau 3. Mehrere Clients Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 1 Lernziele • Sie können mit Java Socket-Verbindungen zu verschiedenen Diensten herstellen • Sie wissen wie die Kommunikation zwischen Client und Server aufgebaut wird • Sie können mit Java ServerSocket-Dienste selbst erstellen • Sie wissen wie ein Server aufgebaut sein muss, um mehrere Clients bedienen zu können Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37_Sockets-P.ppt, V20 2004 © Diego Schmidlin K37 Sockets Folie 2 Seite 1 FHZ Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K37 Sockets 1.1 Client-Sockets: Adressierung (1) • Zur Adressierung von Rechnern im Netz wird die Klasse InetAddress des Pakets java.net verwendet • Ein InetAddress-Objekt enthält sowohl eine IPAdresse als auch den symbolischen Namen des jeweiligen Rechners • Die beiden Bestandteile können mit den Methoden getHostName() und getHostAddress() abgefragt werden • Mit Hilfe von getAddress() kann die IP-Adresse auch direkt als byte-Array mit vier Elementen beschafft werden Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 3 1.1 Client-Sockets: Adressierung (2) • Wichtigste Methoden Methode Beschreibung String getHostName() Liefert Host-Name String getHostAddress() Liefert IP-Adresse des Host byte[] getAddress() Liefert IP-Adresse des Host als byte-Array • Erzeugung eines InetAddress-Objektes Methode Beschreibung public static InetAddress getByName(String host) throws UnknownHostException Liefert ein InetAddress-Objekt für einen beliebigen Host. Host kann als IP-Adresse oder als Hostname übergeben werden public static InetAddress getLocalHost() throws UnknownHostException Liefert ein InetAddress-Objekt für den lokalen Host Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37_Sockets-P.ppt, V20 2004 © Diego Schmidlin K37 Sockets Folie 4 Seite 2 FHZ Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K37 Sockets 1.1 Beispiel // Listing SocketClient1 import java.net.*; public class SocketClient1 { public static void main(String[] args) { if (args.length != 1) { System.err.println("Usage: java SocketClient1 <host>"); System.exit(1); } try { //Get requested address InetAddress addr = InetAddress.getByName(args[0]); System.out.println(addr.getHostName()); System.out.println(addr.getHostAddress()); } catch (UnknownHostException e) { System.err.println(e.toString()); System.exit(1); } } } Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 5 1.2 Client-Sockets: Einfache Verbindung (1) • Als Socket bezeichnet man eine streambasierte Programmierschnittstelle zur Kommunikation zweier Rechner in einem TCP/IP-Netz • Sockets wurden Anfang der achtziger Jahre für die Programmiersprache C entwickelt und mit Berkeley UNIX 4.1/4.2 allgemein eingeführt • Das Übertragen von Daten über eine SocketVerbindung ist ähnlich dem Zugriff auf eine Datei: – Aufbau einer Verbindung – Daten werden gelesen und/oder geschrieben – Abbau der Verbindung • In Java ist Socket-Programmierung sehr einfach Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37_Sockets-P.ppt, V20 2004 © Diego Schmidlin K37 Sockets Folie 6 Seite 3 FHZ Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K37 Sockets 1.2 Client-Sockets: Einfache Verbindung (2) • Im wesentlichen sind dazu zwei Klassen notwendig – Socket für Client-Anwendung – ServerSocket für Server-Anwendung • Socket – Wichtigste Konstruktoren public Socket(String host, int port) throws UnknownHostException, IOException) public Socket(InetAddress address, int port) throws UnknownHostException, IOException) Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 7 1.2 Client-Sockets: Einfache Verbindung (3) • Wichtigste Methoden Methode Beschreibung InputStream getInputStream() throws IOException Gibt InputStream auf einem Socket zurück OutputStream getOutputStream() throws IOException Gibt OutputStream auf einem Socket zurück • Diese Streams können entweder direkt verwendet oder mit Hilfe der Filterstreams in einen bequemer zu verwendenden Streamtyp geschachtelt werden • Nach Ende der Kommunikation sollten sowohl die Eingabe- und Ausgabestreams als auch der Socket selbst mit close geschlossen werden! Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37_Sockets-P.ppt, V20 2004 © Diego Schmidlin K37 Sockets Folie 8 Seite 4 FHZ Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K37 Sockets 1.2 Beispiel import java.net.*; import java.io.*; public class SocketDayTimeDemo { public static void main(String[] args) { if (args.length != 1) { System.err.println("Usage: java SocketDayTimeDemo <host>"); System.exit(1); } try { // DayTime Port = 13 Socket sock = new Socket(args[0], 13); InputStream in = sock.getInputStream(); int len; byte[] b = new byte[100]; while ((len = in.read(b)) != -1) { System.out.write(b, 0, len); } in.close(); sock.close(); } catch (IOException e) { System.err.println(e.toString()); System.exit(1); } } } Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 9 1.3 Client-Sockets: Lesen/Schreiben • Lesend Zugriff auf einen Socket wurde im vorangehenden Beispiel erläutert • Schreibender Zugriff soll mit Hilfe des ECHO-Service auf Port 7 demonstriert werden • Das Programm liest so lange die Eingaben des Anwenders und sendet sie an den Server, bis das Kommando QUIT eingegeben wird • Der Server liest die Daten zeilenweise und sendet sie unverändert an unser Programm zurück • Um Lese- und Schreibzugriffe zu entkoppeln, verwendet das Programm einen separaten Thread der die eingehenden Daten liest und auf dem Bildschirm ausgibt Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37_Sockets-P.ppt, V20 2004 © Diego Schmidlin K37 Sockets Folie 10 Seite 5 FHZ Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K37 Sockets 1.3 Beispiel (1) // Listing SocketEchoClient import java.net.*; import java.io.*; public class SocketEchoClient { public static void main(String[] args) { if (args.length != 1) { System.err.println("Usage: java SocketEchoClient <host>"); System.exit(1); } try { Socket sock = new Socket(args[0], 7); InputStream in = sock.getInputStream(); OutputStream out = sock.getOutputStream(); //Timeout setzen sock.setSoTimeout(300); //Ausgabethread erzeugen OutputThread th = new OutputThread(in); th.start(); Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 11 1.3 Beispiel (2) //Schleife für Benutzereingaben BufferedReader conin = new BufferedReader( new InputStreamReader(System.in)); String line = ""; while (true) { //Eingabezeile lesen line = conin.readLine(); if (line.equalsIgnoreCase("QUIT")) { break; } //Eingabezeile an ECHO-Server schicken out.write(line.getBytes()); out.write('\r'); out.write('\n'); //Ausgabe abwarten th.yield(); } Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37_Sockets-P.ppt, V20 2004 © Diego Schmidlin K37 Sockets Folie 12 Seite 6 FHZ Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K37 Sockets 1.3 Beispiel (3) //Programm beenden System.out.println("terminating output thread..."); th.requestStop(); th.yield(); try { Thread.sleep(1000); } catch (InterruptedException e) { } in.close(); out.close(); sock.close(); } catch (IOException e) { System.err.println(e.toString()); System.exit(1); } } } Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 13 Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 14 1.3 Beispiel (4) class OutputThread extends Thread { InputStream in; boolean stoprequested; public OutputThread(InputStream in) { super(); this.in = in; stoprequested = false; } public synchronized void requestStop() { stoprequested = true; } K37_Sockets-P.ppt, V20 2004 © Diego Schmidlin Seite 7 FHZ Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K37 Sockets 1.3 Beispiel (5) public void run() { int len; byte[] b = new byte[100]; try { while (!stoprequested) { try { if ((len = in.read(b)) == -1) { break; } System.out.write(b, 0, len); } catch (InterruptedIOException e) { //nochmal versuchen } } } catch (IOException e) { System.err.println("OutputThread: " + e.toString()); } } } Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 15 2.1 Server-Sockets (1) • Im letzten Abschnitten haben wir uns mit dem Entwurf von Socket-Clients beschäftigt • Nun wollen wir uns das passende Gegenstück ansehen und uns mit der Entwicklung von SocketServern beschäftigen • Auch das ist in Java recht einfach • Der wesentliche Unterschied liegt in der Art des Verbindungsaufbaus, für den es eine spezielle Klasse ServerSocket gibt Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37_Sockets-P.ppt, V20 2004 © Diego Schmidlin K37 Sockets Folie 16 Seite 8 FHZ Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K37 Sockets 2.1 Server-Sockets (2) • Klasse ServerSocket stellt Methoden zur Verfügung um: – auf einen eingehenden Verbindungswunsch zu warten – nach erfolgtem Verbindungsaufbau einen Socket zur Kommunikation mit dem Client zurückzugeben • ServerSocket – Wichtigster Konstruktor public ServerSocket(int port) throws IOException Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 17 2.1 Server-Sockets (3) • Wichtigste Methoden Methode Beschreibung Socket accept() throws IOException Wartet auf einen Verbindungswunsch und blockiert solange. Wird ein Verbindungswunsch empfangen, so wird ein Socket-Objekt erzeugt InputStream getInputStream() throws IOException Gibt InputStream auf einem Socket zurück OutputStream getOutputStream() throws IOException Gibt OutputStream auf einem Socket zurück • Diese Streams können entweder direkt verwendet oder mit Hilfe der Filterstreams in einen bequemer zu verwendenden Streamtyp geschachtelt werden • Nach Ende der Kommunikation sollten sowohl die Eingabe- und Ausgabestreams als auch der Socket selbst mit close geschlossen werden! Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37_Sockets-P.ppt, V20 2004 © Diego Schmidlin K37 Sockets Folie 18 Seite 9 FHZ Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K37 Sockets 2.2 Verbindungsaufbau • Verbindungsaufbau Client Programm Server Programm OutputStream OutputStream InputStream InputStream Socket(host, port) Socket ServerSocket(port) accept() Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 19 2.2 Beispiel // Listing SocketEchoServer import java.net.*; import java.io.*; public class SocketEchoServer { public static void main(String[] args) { try { System.out.println("Warte auf Verbindung auf Port 7..."); ServerSocket echod = new ServerSocket(7); Socket socket = echod.accept(); System.out.println("Verbindung hergestellt"); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); int c; while ((c = in.read()) != -1) { out.write((char)c); System.out.print((char)c); } System.out.println("Verbindung beenden"); socket.close(); echod.close(); } catch (IOException e) { System.err.println(e.toString()); System.exit(1); } } } Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37_Sockets-P.ppt, V20 2004 © Diego Schmidlin K37 Sockets Folie 20 Seite 10 FHZ Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K37 Sockets 2.3 Server-Sockets: Mehrere Clients (1) • Wir wollen das im vorigen Abschnitt vorgestellte Programm nun in mehrfacher Hinsicht erweitern: – Der Server soll mehrere Clients gleichzeitig bedienen können – Die Clients sollen zur besseren Unterscheidung durchnumeriert werden – Beim Verbindungsaufbau soll der Client eine Begrüssungsmeldung erhalten – Für jeden Client soll ein eigener Worker-Thread angelegt werden Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 21 2.3 Beispiel (1) // Listing SocketEchoServerMT import java.net.*; import java.io.*; public class SocketEchoServerMT { public static void main(String[] args) { int cnt = 0; try { System.out.println("Warte auf Verbindungen auf Port 7..."); ServerSocket echod = new ServerSocket(7); while (true) { Socket socket = echod.accept(); (new EchoClientThread(++cnt, socket)).start(); } } catch (IOException e) { System.err.println(e.toString()); System.exit(1); } } } Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37_Sockets-P.ppt, V20 2004 © Diego Schmidlin K37 Sockets Folie 22 Seite 11 FHZ Hochschule Technik+Architektur Luzern Abteilung Informatik, Fach Programmieren K37 Sockets 2.3 Beispiel (2) class EchoClientThread extends Thread { private int name; private Socket socket; public EchoClientThread(int name, Socket socket) { this.name = name; this.socket = socket; } Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37 Sockets Folie 23 2.3 Beispiel (3) public void run() { String msg = "EchoServer: Verbindung " + name; System.out.println(msg + " hergestellt"); try { InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); out.write((msg + "\r\n").getBytes()); int c; while ((c = in.read()) != -1) { out.write((char)c); System.out.print((char)c); } System.out.println("Verbindung " + name + " wird beendet"); socket.close(); } catch (IOException e) { System.err.println(e.toString()); } } } Abteilung Informatik, Fach Programmieren 2004 © Diego Schmidlin V20 K37_Sockets-P.ppt, V20 2004 © Diego Schmidlin K37 Sockets Folie 24 Seite 12