Socket-Programmierung in Java Abdelmajid Khelil Inhalt • • • • • • • • • • Das Referenzmodell für offene Systeme Kommunikationsprotokolle Socket-Definition TCP-Sockets UDP-Sockets Eigener TCP-Server Programmieren TCP Client-Server Beispiel UDP Client-Server Beispiel SMTP Email-Client Programmieren Arbeiten mit URLs Java Kompaktkurs Socket Programmierung 2 Das Referenzmodell für offene Systeme Java Kompaktkurs Socket Programmierung 3 Verbindungsarten • Man unterscheidet in der Datenkommunikation zwischen zwei Arten von Protokollen: • Verbindungsorientiert: (Telefon-System) – Vor dem Austausch von Daten wird eine Verbindung zum Kommunikationspartner hergestellt. – Hat meist einen höheren Verarbeitungsaufwand im Rechner. – Drei Phasen sind notwendig: Verbindungsaufbau, Datentransfer, Verbindungsabbau – Anwendungen: Datentransfer • Verbindungslos (Post-System) – – – – Einzelne Nachrichten werden versendet . Transport von in sich abgeschlossenen Nachrichten (Datagramme), zustandslos. Hat meist einen höheren Verarbeitungsaufwand im Netz. Anwendungen: Datenbanken, transaktionale Systeme. Java Kompaktkurs Socket Programmierung 4 TCP/IP versus UDP/IP • TCP (Transfer Control Protocol) – Ein Verbindungsorientiertes Protokoll auf der Transportschicht (4). – TCP ist eine sichere, strom-orientierte, bidirektionale Verbindung • UDP (User Datagram Protocol) – Verbindungsloses Protokoll auf der Transportschicht (4). – UDP ist eine unsichere Verbindung für Paketverkehr. – Unzuverlässig: Weder die Auslieferung noch deren Reihenfolge ist garantiert – Schnell. • IP (Internet Protocol) – Verbindungsloses Protokoll auf der Vermittlungsschicht (3). Java Kompaktkurs Socket Programmierung 5 Ports • Def. TCP und UDP Protokolle verwenden Ports, um eintreffende Daten zum betroffenen laufenden Prozess weiterzuleiten. • Bekannte Services: ftp telnet smtp login Java Kompaktkurs (tcp) (tcp) (tcp) (tcp) 21 23 25 513 Socket Programmierung 6 Verbindungsaufbau • 1. Schritt • 2. Schritt Java Kompaktkurs Socket Programmierung 7 Prinzip • Der Server ruft bind und listen auf: • Der Client ruft connect auf: • Der Server ruft accept auf: • Verbindungsarten: – UDP (Datagram) – TCP (Stream) Java Kompaktkurs Socket Programmierung 8 Definition • Ein Socket (Steckdose, Buchse) ist eine Datenstruktur zur Administration von (Netzwerk-) Verbindungen. Ein Socket ist ein Endpunkt einer bidirektionalen Kommunikationsbeziehung zwischen zwei im Netz laufenden Programmen (Prozessen). • Ein Socket ist mit einer Portnummer verbunden so, dass TCPSchicht die Anwendung identifizieren kann, für die die Daten gesendet wurden. • Richtung: – Client Socket: – Server Socket: Java Kompaktkurs Verbindung mit existierendem Dienst Stellt Dienst zur Verfügung Socket Programmierung 9 Warum Java Sockets? • Zwei wichtige Vorteile gegenüber RMI: – Kommunizieren mit nicht-java Objekten und Programmen. – Kommunizieren mit Effizienz: Die Objektserialisierung erfordert einen erhöhten Rechenaufwand und führt zur Übertragung größerer Datenvolumen. • Vorteile von RMI: – RMI liefert mehr Flexibilität: Neue Klassen können von einem anderen Rechner dynamisch zur Applikation hinzugeladen werden. Java Kompaktkurs Socket Programmierung 10 TCP-Sockets • TCP ist eine sichere, strom-orientierte, bidirektionale Verbindung. Als Endpunkte dienen ein Socket beim Klienten und ein ServerSocket beim Server. • Die Ströme erhält man mit getInputStream() und getOutputStream() , • Die Kommunikation erfolgt mit read() und write() • Typische Anwendungsbeispiele sind die meisten InternetProtokolle: FTP, HTTP, SMTP, TELNET Java Kompaktkurs Socket Programmierung 11 TCP-Sockets: die wichtigsten Klassen • java.net .Socket .ServerSocket .DataInputStream .PrintStream .DataOutputStream .URL .URLConnection Java Kompaktkurs Socket Programmierung 12 UDP-Sockets • UDP: Universal ("unreliable") Datagram Protocol • UDP ist eine unsichere Verbindung für Paketverkehr. Als Endpunkte dienen je ein DatagramSocket bei Klient und Server, über die DatagramPacket-Objekte mit send() verschickt und mit receive() empfangen werden. • Die Paket-Größe ist limitiert. • Typische Anwendungsbeispiele sind – informative Internet-Protokolle wie DNS, NIS, TFTP sowie – eine Variante der Remote Procedure Calls und darauf aufbauend NFS. Java Kompaktkurs Socket Programmierung 13 UDP-Sockets: die wichtigsten Klassen (1) • java.net.DatagramPacket – Nur Aufbau von Datenstruktur, keine Verbindung! – Wichtige Konstruktoren ! DatagramPacket(byte[] buf, int length): Zum Empfang von length Bytes in buf ! DatagramPacket(byte[] buf, int length, InetAddress address, int port): Zum Versenden von length Bytes aus buf an address und port – Wichtige Methoden ! byte[] ! void ! int ! void ! void ! void Java Kompaktkurs getData() setData(byte[] buf) getLength() setLength(int length) setAddress(InetAddress iaddr) setPort(int iport) Socket Programmierung 14 UDP-Sockets: die wichtigsten Klassen (2) • java.net.DatagramSocket – Repräsentiert die eigentliche Verbindung – Wichtige Konstruktoren ! DatagramSocket() ! DatagramSocket(int port) – Wichtige Methoden ! void send(DatagramPacket p) throws IOException ! void receive(DatagramPacket p) throws IOException ! void close() • java.net.MulticastSocket – Ist vollständig von der oben beschriebenen Klasse DatagramSocket abgeleitet – Für einen netzwerkweiten Datagram-“Broadcast“ Java Kompaktkurs Socket Programmierung 15 Der Client (TCP) 1. Schritt: Ein Socket Objekt erzeugen (Öffnen eines Sockets): Socket Client = new Socket(“hostname”,portNumber); 2. Schritt: Ein “output stream” erzeugen, um Daten zu senden: PrintStream out = new PrintStream(Client.getOutputStream()); bzw. DataOutputStream out2 = new DataOutputStream(Client.getOutputStream()); 3. Schritt: Ein “input stream” erzeugen, um die Antwort des Servers zu empfangen: DataInputStream in = new DataInputStream(Client.getInputStream()); bzw. BufferedReader in = new BufferedReader( new InputStreamReader(Client.getInputStream())); 4. Schritt: Nutzdaten senden und empfangen. in.readLine(); out.println(); aber out2.writeBytes(); 5. Schritt: Ströme schließen: out.close(); in.close(); 6. Schritt: Socket schliessen: client.close(); Java Kompaktkurs Socket Programmierung 16 Der Server (TCP) 1. Schritt: Ein ServerSocket Objekt erzeugen: ServerSocket listenSocket = new ServerSocket(portNumber); 2. Schritt: Ein Socket Objekt aus dem ServerSocket erzeugen: While (someCondition) { Socket server = listenSocket.accept(); doSomethingWith(server); } 3. Schritt: Ein “input stream” erzeugen: DataInputStream in = new DataInputStream(server.getInputStream()); 4. Schritt: Ein “output stream” erzeugen: PrintStream out = new PrintStream(server.getOutputStream()); 5. Schritt: Nutzdaten senden und empfangen. in.readLine(); out.println(); 6. Schritt: Ströme schließen: 7. Schritt: Socket schliessen: Java Kompaktkurs out.close(); in.close(); server.close(); Socket Programmierung 17 Kompilieren und ausführen • Kompilieren der java-Quelldateien: javac Client.java javac Server.java • Ausführen der Testszenarien – TCP: Starten des Servers mit: java Server Starten des Clients (in einer zweiten Shell) mit: java Client Ggf. starten eines weiteren Clients. Beenden des Servers (mit Crtl-C). – [UDP analog] Java Kompaktkurs Socket Programmierung 18 Eigener TCP-Server Programmieren Der Server – Ist mit jedem Telnet-Client-Programm aufrufbar, – Echot die Eingaben und – Wird durch Eingabe der Zeichenfolge ’ciao’ beendet Damit dies Internet-weit erfolgen kann, muss der eigene Rechner über eine IP-Verbindung angeschlossen sein: Zu Testzwecken kann der Server zunächst mit dem Telnet-Client-Programm vom eigenen Rechner genutzt werden (TCP/IP-Protokoll muss allerdings installiert sein): telnet 127.0.0.1 7788 Der Ablauf – Server-Programm mit Java erstellen – Server auf dem eigenen Rechner starten und laufen lassen – während der Server läuft, ist er im Internet über die Internet-Adresse und dem gewählten Port (im Beispiel 7788) erreichbar. Java Kompaktkurs Socket Programmierung 19 Eigener TCP-Server: SimpleServer.java • Das Serverprogramm SimpleServer.java besteht aus zwei Klassen: • SimpleServer – Die zentrale Applikations-Klasse SimpleServer erstellt die SocketVerbindungen zu "anrufenden" Verbindungen. Jede Telnet-Verbindung zu SimpleServer ist eine eigene SocketVerbindung. • ServerThread – Die Datenkommunikation über Eingabe- und Ausgabe-Streams erfolgt in der Klasse ServerThread. • Würde die Datenkommunikation nicht als Thread ausgeführt, würde bereits die erste Kommunikationsverbindung den eigenen Server-Rechner vollständig belegen. Java Kompaktkurs Socket Programmierung 20 SimpleServer.java (1) • In der Klasse SimpleServer wird eine Instanz ss von ServerSocket auf dem Port 7788 erstellt. • Die Methode accept() von ServerSocket erwartet Client-Anfragen auf dem Server-Socket • Liegt eine Anfrage vor, wird ein neuer Thread ServerThread gestartet, der die Client-Anforderung bedient (jede SocketServerSocket-Verbindung ist somit ein eigener Thread) Java Kompaktkurs Socket Programmierung 21 SimpleServer.java (2) import java.io.*; // import der Klassen für Streams import java.net.*; // import der Klassen für Netzwerkkommunikation public class SimpleServer { public static void main(String args[]) { int anz = 1; try { ServerSocket ss = new ServerSocket(7788); while(true) { Socket sverb = ss.accept(); System.out.println(" Verbindung " + anz); new ServerThread(sverb,anz).start(); anz++; } } catch (Exception e) { System.out.println(e); } } } Java Kompaktkurs Socket Programmierung 22 SimpleServer.java (3) • In der Klasse ServerThread wird eine Instanz sverb der Klasse Socket erstellt. • Die Streams DataInputStream und PrintStream werden genutzt, zur Abwicklung der über die Socket-Verbindung eingehenden und ausgehenden Datenströme Java Kompaktkurs Socket Programmierung 23 SimpleServer.java (4) class ServerThread extends Thread { Socket sverb; int nverb; /* Konstruktor von ServerThread wird bei jeder neuen Verbindung aus aufgerufen */ SimpleServer ServerThread (Socket s , int n) { this.sverb = s; this.nverb = n; } public void run () { try { /** Verwaltet den Eingabestream der Socketverbindung */ DataInputStream in = new DataInputStream(sverb.getInputStream()); /** Verwaltet den Ausgabestream der Socketverbindung */ PrintStream out = new PrintStream(sverb.getOutputStream()); out.println( "Hallo - Willkommen beim Simple-Echo-Server!\r\n"); Java Kompaktkurs Socket Programmierung 24 SimpleServer.java (5) boolean weiter = true; while (weiter) { String str = in.readLine(); if (str == null) weiter = false; else { out.println("Enter ciao "+nverb+" : "+str); if (str.trim().equals("ciao")) weiter=false; } // Ende if } // Ende while sverb.close(); } catch (IOException e) { System.out.println(e); } } // Ende run() } // Ende SimpleServer Java Kompaktkurs Socket Programmierung 25 TCPClient.java (1) import java.io.*; import java.net.*; /** Testprogramm für einen TCP Client * Dem Client wird per Kommandozeile ein Satz eingegeben, der an den * Server gesendet wird. Nach erhalt der Antwort beendet sich der * Client. */ class TCPClient { /**Exceptions, die auftreten können, werden durchgereicht public static void main(String args[]) throws java.net.SocketException, java.io.IOException { /** Nachricht, die an den Server geschickt wird */ String sentence; /** Nachricht, die vom Server empfangen wird */ String modifiedSentence; /** Objekt, dass Benutzerdaten einliest */ BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in)); Java Kompaktkurs Socket Programmierung 26 TCPClient.java (2) /** Stellt die Verbindung zum Server auf Port 6789 her. In diesem Fall läuft der Server auf dem gleichen Rechner wie der Client. */ Socket clientSocket = new Socket("localhost", 6789); DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream()); /** Verwaltet den Eingabestream der Socketverbindung , 2. Möglichkeit*/ BufferedReader inFromServer = new BufferedReader( new InputStreamReader(clientSocket.getInputStream())); /** Der Benutzer gibt einen Satz ein */ sentence = inFromUser.readLine(); Java Kompaktkurs Socket Programmierung 27 TCPClient.java (3) /* Der Satz wird über den Ausgabestream der Socketverbindung an den Server gesendet. */ outToServer.writeBytes(sentence +'\n'); /* Es wird auf die Nachricht vom Server gewartet und diese Empfangen */ modifiedSentence = inFromServer.readLine(); /* Die Antwort wird auf der Konsole ausgegeben */ System.out.println("FROM SERVER: "+ modifiedSentence); /* Der Client schliesst die Socketverbindung */ clientSocket.close(); } } // Programmende Java Kompaktkurs Socket Programmierung 28 TCPServer.java (1) import java.io.*; import java.net.*; /** Testprogramm für einen TCP Server Der Server empfängt Nachrichten, wandelt sie in Grossbuchstaben und sendet sie zurück. */ class TCPServer { public static void main(String args[]) throws java.net.SocketException, java.io.IOException { /** Die vom Client gesendete Nachricht */ String clientSentence; /** Die Antwort fuer den Client */ String capitalizedSentence; /** Der Serverdienst wird auf Port 6789 aufgesetzt */ ServerSocket welcomeSocket = new ServerSocket(6789); while(true) { /** Eingehende TCP Verbindungen werden an einen eigenen (virtuellen) Socket weitergereicht, über den die eigentliche Kommunikation stattfindet (Damit mehrere Anfragen gleichzeitig bearbeitet werden können, müsste dieser Teil durch Threads parallelisiert werden.) */ Socket connectionSocket = welcomeSocket.accept(); Java Kompaktkurs Socket Programmierung 29 TCPServer.java (2) BufferedReader inFromClient = new BufferedReader( new InputStreamReader(connectionSocket.getInputStream())); DataOutputStream outToClient = new DataOutputStream( connectionSocket.getOutputStream()); clientSentence = inFromClient.readLine(); /* Wandele die Nachricht in Grossbuchstaben */ capitalizedSentence = clientSentence.toUpperCase() + '\n'; /* Sende die Antwort an den Client */ outToClient.writeBytes(capitalizedSentence); /* Der Server schliesst die Socketverbindung nicht. Weitere * Anfragen über diesen Socket werden jedoch nicht beachtet. */ } // Ende der Schleife } // Ende von main (wird nie erreicht) } Java Kompaktkurs Socket Programmierung 30 UDPClient.java (1) import java.io.*; /* import der Klassen fuer Streams */ import java.net.*; /* import der Klassen fuer Netzwerkkommunikation */ /** Testprogramm fuer einen UDP Client. Dem Client wird per Kommandozeile ein Satz eingegeben, der an den Server gesendet wird. Nach erhalt der Antwort beendet sich der Client. */ class UDPClient { public static void main(String args[]) throws java.net.SocketException, java.io.IOException { BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in)); /** Erstellt einen UDP Socket */ DatagramSocket clientSocket = new DatagramSocket(); /** Enthält die IP Adresse des Servers. In diesem Fall laeuft der * Server auf dem gleichen Rechner wie der Client. */ InetAddress IPAddress = InetAddress.getByName("localhost"); Java Kompaktkurs Socket Programmierung 31 UDPClient.java (2) byte[] sendData = new byte[1024]; /* Datenpuffer fuer ausgehende Pakete */ byte[] receiveData = new byte[1024]; /* Datenpuffer fuer eingehende Pakete */ String sentence = inFromUser.readLine(); /* Der Benutzer gibt einen Satz ein */ sendData = sentence.getBytes(); /* Der Satz wird in den Sendepuffer kopiert */ /* Aus dem Sendepuffer wird ein UDP Paket "geschnuert"; Zieladresse ist der UDPServer auf dem Port 9876 */ DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876); clientSocket.send(sendPacket); /* das UDP Paket wird ueber Socket verschickt */ DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); /* Variable fuer eingehende UDP Pakete */ /* Warten auf eingehende UDP Pakete; weiter, wenn Paket eingetroffen */ clientSocket.receive(receivePacket); Java Kompaktkurs Socket Programmierung 32 UDPClient.java (3) /** Lese die Antwort des Servers aus dem emfangenem UDP Paket aus */ String modifiedSentence = new String(receivePacket.getData()); /* Die Antwort wird auf der Konsole ausgegeben */ System.out.println("FROM SERVER: " +modifiedSentence); /* Schliessen des Sockets */ clientSocket.close(); } } Java Kompaktkurs Socket Programmierung 33 UDPServer.java (1) import java.io.*;import java.net.*; /** Testprogramm fuer einen UDP Server * Der Server empfaengt Nachrichten, wandelt sie in Grossbuchstaben und * sendet sie zurueck. */ class UDPServer { public static void main(String args[]) throws java.net.SocketException, java.io.IOException { /** Erstellt einen UDPSocket der auf Port 9876 Verbindungen entgegennimmt */ DatagramSocket serverSocket = new DatagramSocket(9876); byte[] receiveData = new byte[1024]; /** Datenpuffer fuer eingehende Pakete */ byte[] sendData = new byte[1024]; /** Datenpuffer fuer ausgehende Pakete */ while(true){ /** Variable fuer eingehende UDP Pakete */ DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); Java Kompaktkurs Socket Programmierung 34 UDPServer.java (2) /* Warten auf eingehende UDP Pakete; weiter, wenn Paket eingetroffen */ serverSocket.receive(receivePacket); /* Lese die Nachricht des Clients aus dem emfangenem UDP Paket aus */ String sentence = new String(receivePacket.getData()); /* Die IP Adresse des Clients */ InetAddress IPAddress = receivePacket.getAddress(); /* Der Port auf dem der Client erreichbar ist */ int port = receivePacket.getPort(); String capitalizedSentence = sentence.toUpperCase(); /* Kopiere die Antwort in den Sendepuffer */ sendData = capitalizedSentence.getBytes(); /** "Schnüre" das Paket für den Client (seine IP Adresse und * Port wurden Zwischengespeichert) */ DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); serverSocket.send(sendPacket); /* Verschicke das Paket */ } } } Java Kompaktkurs Socket Programmierung 35 SMTP • Lieferung von Mails im Internet: – Die Client-Maschine etabliert eine TCP-Verbindung zu Port 25 der ServerMaschine. – An diesem Port befindet sich ein Email SMTP-Dämon (simple mail transfer protocol). – Dämon akzeptiert eintreffende Verbindungen. – Dämon kopiert Email-Nachrichten in Mailbox. – Wenn die Nachricht nicht zulieferbar ist, ein Fehler-Bericht wird zum Sender zurückgegeben. • Im folgenden ein SMTP-Client in Java Java Kompaktkurs Socket Programmierung 36 SMTP client (1) import java.io.*; import java.net.*; public class smtpClient { public static void main(String[] args) { Socket smtpSocket = null; DataOutputStream os = null; DataInputStream is = null; // Port 25 ist reserviert für SMTP try { smtpSocket = new Socket("hostname", 25); os = new DataOutputStream(smtpSocket.getOutputStream()); is = new DataInputStream(smtpSocket.getInputStream()); Java Kompaktkurs Socket Programmierung 37 SMTP client (2) } catch (UnknownHostException e) { System.err.println("Don't know about host: hostname"); } catch (IOException e) { System.err.println("Couldn't get I/O for the connection to: hostname"); } // If everything has been initialized then we want to write some data // to the socket we have opened a connection to on port 25 if (smtpSocket != null && os != null && is != null) { try { // The capital string before each colon has a special meaning to SMTP // you may want to read the SMTP specification, RFC1822/3 Java Kompaktkurs Socket Programmierung 38 SMTP client (3) os.writeBytes("HELO\n"); os.writeBytes("MAIL From: [email protected]\n"); os.writeBytes("RCPT To: [email protected]\n"); os.writeBytes("DATA\n"); os.writeBytes("From: [email protected]\n"); os.writeBytes("Hi there\n"); // message body os.writeBytes("\n.\n"); os.writeBytes("QUIT"); // keep on reading from/to the socket till we receive the "Ok" from SMTP, // once we received that then we want to break. String responseLine; while ((responseLine = is.readLine()) != null) { Java Kompaktkurs Socket Programmierung 39 SMTP client (4) System.out.println("Server: " + responseLine); if (responseLine.indexOf("Ok") != -1) {break;} } os.close(); is.close(); smtpSocket.close(); } catch (UnknownHostException e) { System.err.println("Trying to connect to unknown host: " + e); } catch (IOException e) { System.err.println("IOException: " + e); } } } } Java Kompaktkurs Socket Programmierung 40 Arbeiten mit URLs • URL (Uniform Resource Locator) ist – Ein Verweis (Adresse) für eine Ressource im Internet – Eine Klasse in java.net 1. Schritt: Erzeugen einer URL. URL meine_url = new URL("http://www.informatik.uni-stuttgart.de"); 2. Schritt: Öffnen einer Verbindung zur URL URLConnection url_connect = meine_url.openConnection(); 3. Schritt: Erhalten eines Ausgabestroms aus der Verbindung. (Dieser Ausgabestrom kann z.B. mit dem Standardeingabestrom des cgi-bin-Skripts auf dem Server verbunden werden). DataInputStream dis = new DataInputStream(meine_url.openStream()) 4. Schritt: Schreiben in den Ausgabestrom. 5. Schritt: Schließen des Ausgabestroms. Java Kompaktkurs Socket Programmierung 41 URL- Beispiel (1) import java.io.*; import java.net.*; public class URLConnectionTest { public static void main(String[] args) { if (args.length == 0) { System.err.println("Usage: URLConnectionTest <host> [<user> <password>]"); return; } try { URL url = new URL(args[0]); URLConnection connection = url.openConnection(); // set username, password if specified on command line Java Kompaktkurs Socket Programmierung 42 URL- Beispiel (2) // set username, password if specified on command line if (args.length > 2) { String username = args[1], password = args[2]; String encoding = base64Encode(username + ":" + password); connection.setRequestProperty("Authorization", "Basic " + encoding); } connection.connect(); // print header fields String key; for (int n = 1; (key = connection.getHeaderFieldKey(n)) != null; ++n) { String value = connection.getHeaderField(n); System.out.println(key + ": " + value); } Java Kompaktkurs Socket Programmierung 43 URL- Beispiel (3) // print convenience functions System.out.println("----------"); System.out.println("getContentType: " + connection.getContentType()); System.out.println("getContentLength: " + connection.getContentLength()); System.out.println("getContentEncoding: " + connection.getContentEncoding()); System.out.println("getDate: " + connection.getDate()); System.out.println("getExpiration: " + connection.getExpiration()); System.out.println("getLastModifed: " + connection.getLastModified()); System.out.println("----------"); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); Java Kompaktkurs Socket Programmierung 44 URL- Beispiel (4) String line; // print first ten lines of contents for (int n = 1; (line = in.readLine()) != null && n <= 10; ++n) System.out.println(line); if (line != null) System.out.println(". . ."); }catch (IOException e) { System.out.println(e); } } public static String base64Encode(String s) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); Base64OutputStream out = new Base64OutputStream(bOut); try { out.write(s.getBytes()); } catch (IOException e) { out.flush(); } return bOut.toString(); } } Java Kompaktkurs Socket Programmierung 45 URL- Beispiel (5) /* BASE64 encoding encodes 3 bytes into 4 characters. |11111122|22223333|33444444| Each set of 6 bits is encoded according to the toBase64 map. If the number of input bytes is not a multiple of 3, then the last group of 4 characters is padded with one or two = signs. Each output line is at most 76 characters. */ class Base64OutputStream extends FilterOutputStream { public Base64OutputStream(OutputStream out) { super(out); } public void write(int c) throws IOException { inbuf[i] = c; i++; if (i == 3) { super.write(toBase64[(inbuf[0] & 0xFC) >> 2]); super.write(toBase64[((inbuf[0] & 0x03) << 4) | ((inbuf[1] & 0xF0) >> 4)]); super.write(toBase64[((inbuf[1] & 0x0F) << 2) | ((inbuf[2] & 0xC0) >> 6)]); super.write(toBase64[inbuf[2] & 0x3F]); Java Kompaktkurs Socket Programmierung 46 URL- Beispiel (6) col += 4; i = 0; if (col >= 76) { super.write('\n'); col = 0; } } } public void flush() throws IOException { if (i == 1) { super.write(toBase64[(inbuf[0] & 0xFC) >> 2]); super.write(toBase64[(inbuf[0] & 0x03) << 4]); super.write('='); super.write('='); } Java Kompaktkurs Socket Programmierung 47 URL- Beispiel (7) else if (i == 2) { super.write(toBase64[(inbuf[0] & 0xFC) >> 2]); super.write(toBase64[((inbuf[0] & 0x03) << 4) | ((inbuf[1] & 0xF0) >> 4)]); super.write(toBase64[(inbuf[1] & 0x0F) << 2]); super.write('='); } } private static char[] toBase64 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', Java Kompaktkurs Socket Programmierung 48 URL- Beispiel (8) 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; private int col = 0; private int i = 0; private int[] inbuf = new int[3]; } Ein Aufrufbeispiel ist java URLConnectionTest http://www.informatik.unistuttgart.de/ipvr/vs/lehre/ws0001/KompaktKurs/index.html Java Kompaktkurs Socket Programmierung 49 Zusammenfassung • Client-Server Programmierung in Java ist einfach. • Das Package java.net stellt eine sehr mächtige und flexible Infrastruktur für Netzprogrammierung zur Verfügung. • Die Packages Sun.* stellen auch sehr gute Klassen zur Verfügung, werden aber stetig aktualisiert und einige sind nicht portable. Java Kompaktkurs Socket Programmierung 50