3 Verbindungslose Kommunikation mit UDP Das User Datagram Protocol (DDP) stellt grundlegende Punktionen zur Verfügung, um mit geringem Aufwand Daten zwischen kommunizierenden Prozessen austauschen zu können. UDP ist als Transportprotokoll der dritten Schicht im TCP/IP-Schichtenmodell zugeordnet und nutzt den Vermittlungsdienst IP. 3.1 Das Protokoll UDP DDP ist ein verbindungsloses Protokoll. d. h. es bietet keinerlei Kontrolle über die sichere Ankunft versendeter Datenpakete, so genannter Datagramme. DDP ist im RFC (Request for Comments) 768 der IETF (Internet Engineering Task Force) spezifiziert (siehe auch http://www. i etf. org/rfc/rfc768.txt). Datagramme müssen nicht den Empfänger in der Reihenfolge Datagramm erreichen, in der sie abgeschickt werden. Datagramme können verloren gehen, weder Sender noch Empfänger werden über den Verlust informiert. Fehlerhafte Datagramme werden nicht nochmals übertragen. Bild 3.1 zeigt den Aufbau des UDP-Datagramms. das in ein IPv4Paket eingebettet ist. -----r- • - , ... 4- IPv4-Kopfteil - UDP-Kopftei I ---+---- UDP-Nutzdaten -----*----- IP-Adresse des Senders IP-Adresse des Empfängers ... -T-----20 Byte _ _L _ --r----0- 40 Byte Portnummer des Senders Portnummer des Empfängers Länge des Datagramms Prüfsumme Nutzdaten Bild3.!· __J _ 8 Byte Aufbau des UDPDatagramms 3 100 Verbindungslose Kommunikation mit UDP Der UDP-Kopfteil enthält vier 16 Bit lange Felder, • die Portnummer des Senders, • die Portnummer des Empfängers, • die Gesamtlänge des UDP-Datagramms und • die Prüfsumme. Darauf folgen dann die eigentlichen Nutzdaten des Datagramms. Die Maximallänge eines UDP-Datagramms ist begrenzt. Anwendungen sollten nicht mehr als 508 Byte Nutzdaten in einem Datagramm versenden, um Probleme infolge einer evtl. nötigen Fragmentierung des IP-Pakets durch Router zu vermeiden. UDP ist ein einfaches Mittel, um Nachrichten, die keine zuverlässige übertragung erfordern. zu versenden. UDP hat gegenüber TCP den Vorteil eines viel geringeren Kontroll-Overheads (8 Byte bei DDP. 20 Byte bei TCP). UDP-Anwendungen Einige bekannte Anwendungen, die UDP nutzen, sind: • das Domain Name System (DNS) zur automatischen Konvertierung von Domain-Namen (Rechnernamen) in IP-Adressen und umgekehrt. • das Simple Network Management Protocol (SNMP) zur Verwaltung von Ressourcen in einem TCP/IP-basierten Netz, • das Trivial File Transfer Protocol (TFTP). das einen einfachen Dateitransferdienst zum Sichern und Laden von System- und Konfigurationsdateien bietet, • das Dynamic Host Configuration Protocol (DHCP) zur dynamischen Zuweisung von IP-Adressen. Die unidirektionale übertragung von Video- und Audiosequenzen zur Wiedergabe in Echtzeit (Multimedia Streaming) ist besonders zeitkritisch. Der gelegentliche Verlust eines Datenpakets kann aber toleriert werden. Hier ist UDP sehr gut geeignet. 3.2 DatagramSocket und DatagramPacket Java-Programme nutzen so genannte Sockets als Programmierschnittstelle für die Kommunikation über DDP/IP und TCP/IP. Sockets stellen die Endpunkte einer Kommunikationsbeziehung zwischen Prozessen dar. Ein UDP-Socket wird an eine Portnummer auf dem lokalen Rechner gebunden. Er kann dann Datagramme an jeden beliebigen anderen DDP-Socket senden und von jedem beliebigen UDP-Socket empfangen. 3.2 DatagramSocket und DatagramPacket Rechn er A 101 Rechner B Bild32· UDP-Sockets Client Server 1/ IUDP-SoCke:Y IP 10.108.105.95 Port 3963 IP 10.108.105.96 _ Port 50000 I H UDP-Socket I I Die Klasse java. net. DatagramSocket repräsentiert einen UDP- DatagramSocket Socket zum Senden und Empfangen von UDP-Datagrammen. Ein DDP-Socket muss an einen Port des lokalen Rechners gebunden werden. Hierzu stehen Konstruktoren zur Verfügung: DatagramSocket( ) throws Socket Except ion erzeugt einen UDP-Socket und bindet ihn an einen verfügbaren Port des lokalen Rechners. DatagramSocket(int port) throws Socket Exception erzeugt einen UDP-Socket und bindet ihn an die Portnummer port des lokalen Rechners. Hierdurch kann ein Server den Port, den er nutzen möchte, festlegen. Beide Konstruktoren können bei Fehlern im zugrunde liegenden Protokoll die Ausnahme ja va. net. SocketExceptl on auslösen: Socket Exceptlon ist Subklasse von java.lo. IO Exceptlon . Die Klasse java. net. DatagramPacket repräsentiert ein UDP-Data- DatagramPacket gramm. Der Konstruktor DatagramPacket(byte[] buf. int l ength. Inet Addre ss address. int port) erzeugt ein UDP-Datagramm zum Senden von Daten. buf enthält die Daten, addr ess ist die IP-Adresse und port die Portnummer des Empfängers. Die Anzahl 1ength der zu übertragenden Bytes muss kleiner oder gleich der Pufferlänge sein. Der Konstruktor DatagramPacket(byte[] buf. in t length) erzeugt ein UDP-Datagramm zum Empfangen von Daten. buf ist der Puffer. der die empfangenen Daten aufnimmt. 1ength legt fest, wie viele Bytes maximal gelesen werden sollen. l engt h muss kleiner oder gleich der Pufferlänge sein. 3 102 Verbindungslose Kommunikation mit UDP Wendet man auf dieses Paket die Methoden setAdress und setPort (siehe weiter unten) an, so kann es auch gesendet werden. send Die DatagramSocket-Methode void send(DatagramPack et p) t hr ows IOExcept i on sendet ein UDP -Datagramm von diesem Socket aus. receive Die DatagramSocket-Methode vOl d rece;ve(DatagramPacket p) throws IOExcept l on empfängt ein UDP-Datagramm von diesem Socket. p enthält die Daten sowie die IP-Adresse und die Portnummer des Senders. Die Methode blockiert so lange, bis ein Datagramm empfangen "WUrde. Bild 3-3 zeigt den Ablauf zum Senden eines Datagramms in Form eines UML-Sequenzdiagramms. Bild3']· Datagramm senden Anwendung :DatagramSocket I send(packet) Weitere DatagramPacket-Methoden Weitere DatagramPacket-Methoden sind: byte[] getData () liefert den Datenpufferinhalt. i nt getLength () liefert die Länge der Daten, die empfangen wurden bzw. gesendet werden sollen. Inet Address getAddress() liefert die (entfernte) IP-Adresse des Senders (beim empfangenen Datagramm) bzw. des Empfängers (beim zu sendenden Datagramm). 3.3 Ein Echo-Server und -Client 103 i nt getPort() liefert die (entfernte) Portnummer des Senders (beim empfangenen Datagramm) bzw. des Empfängers (beim zu sendenden Datagramm). void setData (byte[] buf) setzt den Datenpuffer des Datagramms. voi d setLength(int leng th) bestimmt die Anzahl Bytes. die gesendet werden sollen bzw. die maximale Anzahl Bytes. die empfangen werden sollen. 1ength muss kleiner oder gleich der Pufferlänge des Datagramms sein. voi d setAddress ( InetAddress address) setzt die IP-Adresse des Rechners, an den das Datagramm gesendet werden soll. void setPort(int port) setzt die Portnummer, an die das Datagramm gesendet werden soll. In allen Beispielen dieses Kapitels ist die Bearbeitungszeit des Servers nach Eintreffen eines Pakets relativ kurz. Deshalb ist eine iterative Implementierung (Paket empfangen - Anfrag e bearbeiten - Paket senden) ausreichend. Bei längeren Bearbeitungszeiten sollten für die Bearbeitung und das Senden der Antwort zu einer Anfrage Threads benutzt werden (parallele Implementierung). um die durchschnittliche Wartezeit eines Clients zu reduzieren. 3.3 Ein Echo-Server und -Client Das erste Programmbeispiel ist eine einfache Client-ServerAnwendung. die den Umgang mit den Methoden des vorigen Abschnitts zeigen soll. Der Client schickt einen Text, den der Server als Echo an den Programm3.l Absender zurückschickt. lmport java net. DatagramPacket; lmport java net. DatagramSocket; public class EchoSer ver ( pri vate static final int BUFSIZE EchoServer ~ 508; public static void main(String[] args) throws Except i on ( int port ~ Int eger .par selnt (ar gs [O] ) ; 3 104 Verbindungslose Kommunikation mit UDP // Socket an Port binden DatagramSocket socket ~ new DatagramSocket(port); // Pakete zum Empfangen bzw. Senden DatagramPacket packet In ~ new DatagramPacket( new byte[BUFSIZEJ. BUFSIZE); DatagramPacket packetOut ~ new DatagramPacket( new byte[BUFSIZEJ. BUFSIZE); System. out. pri nt 1n( "Server gestartet ... "); whi 1e (true) ( // Paket empfangen socket.recelve(packetIn); System. out. pri nt 1n("Recei vcd: " + " bytes"); + packet! n. getLength() // Daten und Länge lm Antwortpaket spelchern packetOut.setData(packetIn.getData()); packetOut.setLength(packetIn.getLength()); // Zieladresse und Zielport im Antwortpaket setzen packetOut.setAddress(packetIn.getAddress()); packetOut.setPort(packetIn.getPort()); // Antwortpaket senden socket.send(packetOut); Bild3.4· Echo-Dienst From: 10.108.105.95 Ta: 10.108.105.96 EchoClient IP: 10.108.105.95 Port: 3963 IP: 10.108.105.96 Port: 50000 From: 10.108.105.96 Ta: 10.108.105.95 EchoServer wird mit dem Parameter Portnummer aufgerufen. Zu Beginn wird ein UDP-Socket erzeugt und an die vorgegebene Portnummer gebunden. Es werden zwei Datagramme zum Ernp- 3.3 105 Ein Echo-Server und -Client fangen bzw. Senden von Daten mit der Pufferlänge 508 Byte erzeugt. In einer Endlos-Schleife werden Daten empfangen und gesendet. Nutzdaten und Datenlänge sowie IP-Adresse und Portnummer werden aus dem empfangenen Paket gelesen und in das zu sendende Paket übertragen. Der Server kann über Tastatur mit Strg+C abgebrochen werden. Das Programm EchoCll ent sendet ein Datagramm an den Server. EchoClient Neben dem Hostnamen und der Portnummer des Servers werden die Nutzdaten des Datagramms als weiterer Parameter beim Aufruf mitgegeben. Erhält der Client nicht innerhalb von zwei Sekunden eine Antwort vom Server, wird eine Ausnahme ausgelöst und das Programm beendet. Diese Zeitsteuerung wird durch Aufruf der folgenden DatagramSocket-Methode erreicht. vOld setSoTimeout(lnt tl meout) throws SocketExceptlon setzt ein Timeout in Millisekunden. recel ve für diesen Socket blockiert höchstens ti neout Millisekunden und löst dann die Ausnahme java. net. SocketTl meoutExceptl on aus. Wird tlmeout = o gesetzt, so wird die Timeout-Steuerung deaktiviert. Socket Tl meoutExceptlon ist Subklasse von java.l o. Interrupted IOExceptl on. int getSoTimeout() throws SocketException liefert die Timeout-Angabe. lmport lmport lmport lmport java java java java net. DatagramPacket; net. DatagramSocket; net. InetAddress; net SocketTl meoutExceptlon; public class EchoClient ( private static final int BUFSIZE private static final int TIMEOUT ~ ~ 508; 2000; public static void main(String[] args) throws Exception { try ( String host ~ args[O]; int port ~ Integer.parse lnt(args[I]); byte[] data ~ args[2].getBytes(); // Socket wlrd an anonymen Port gebunden DatagramSocket socket = new DatagramSocket(); // Maximal TIMEOUT Millisekunden auf Antwort warten socket.setSoTi meout(TIMEOUT); 3 Verbindungslose Kommunikation mit UDP 106 // Paket an Server senden Inet Address addr ~ Inet Address getByName(host); DatagramPacket packetOut ~ new DatagramPacket(data, data,length, addr, port); socket,send (packetOut); // Antwortpaket empfangen DatagramPacket packet In ~ new DatagramPacket( new byte[BUFS IZ EJ, BUFS IZ E); socket.recelve(packet In); Str ing received ~ new String(packet In getData(), 0, packet In,getLength()); System. out. pr i nt l n( "Recel ved: " + rec el ved ) ; socket,close(); catch (SocketTi meoutException e) ( System,err,println("Timeout; " + e getMessage() ); 3.4 Feste Verbindungen Die Klasse Dat agr amSocket enthält eine Methode, die es ermöglicht, die Adresse, an die Datagramme gesendet werden bzw. von der Datagramme empfangen werden, gezielt auszuwählen und alle anderen Datagramme zu verwerfen: vOld connect( InetAddress address, i nt port) Datagramme können nur an diese IP-Adresse/Portnummer gesendet bzw. von dieser IP-Adresse/Portnummer empfangen werden, voi d disconnect() hebt die durch connect hergestellte Restriktion auf, Mit den beiden DatagramSocket-Methoden Inet Address getlnetAddress() und i nt getPort () können die IP-Adresse bzw. die Portnummer, die in connect verwendet "WUrden, abgefragt werden. Wurde connect nicht benutzt, wird null bzw. - I geliefert, Programm 3.2 Der Client Sender schickt kurze Texte aus einer Datei als Datag ramme an den Server. Der Server Recel ver zeigt die empfangenen Daten auf dem Bildschirm an. Er soll nur Datagramme, die von einer bestimmten IP-Adresse und Portnummer aus ge- 3.4 Feste Verbindungen 107 sendet "WUrden, empfangen können. Zu diesem Zweck wird der Server mit drei Parametern aufgerufen: • lokale Portnummer, • IP-Adresse/Rechnemame des Client und • Portnummer des Client, lmport java net.DatagramPacket; lmport java net.DatagramSocket; lmport java net.InetAddress; public class Receiver ( private static final int BUFSIZE Receiver ~ 508; public static void main(String[] args) throws Exception ( int port ~ Integer.parselnt(args[O]); String remoteHost ~ args[I]; int remotePort ~ Int eger .parse lnt (args [2] ) ; OatagramSocket socket ~ new OatagramSocket(port); // Es werden nur Datagramme dleser Adresse // entgegengenommen socket.connect( InetAddress.getByName(remoteHost). remotePort) ; DatagramPacket packet = new DatagramPacket( new byte[BUFSIZE]. BUFSIZE); whi 1e (true) ( socket.recelve(packet); String text ~ new String(packet getOata(). O. packet .getLength ()); System.out.println(packet.getAddress().getHostAddress() + "" " + packet.getPort() + " > " + text); Beim Client Sender wird der DDP-Socket an eine explizit vorgegebene Portnummer gebunden. die beim Aufruf des Programms als Parameter mitgegeben wird. lmport lmport lmport lmport lmport java.lo.BufferedReader; java.lo.FlleReader: java net.DatagramPacket; java net.DatagramSocket; java net.InetAddress; Sender 3 108 Verbindungslose Kommunikation mit UDP public class Sender ( private static final int BUFSIZE ~ 508; public static void main(String [] args) throws Exception ( int localPort ~ Integer.parselnt(args[O]); String host ~ args[I]; int port ~ Integer.parselnt(args[2]); // Socket wlrd an vorgegebenen Port gebunden OatagramSocket socket ~ new OatagramSocket(localPort); InetAddress addr ~ InetAddress.getByName(host); DatagramPacket packet = new OatagramPacket( new byte[BUFSIZE]. BUFSIZE. addr. port); BufferedReader in ~ new BufferedReader( new Fi1eReader("ei ngabe.t xt ") ) ; Strlng I i ne ; whi 1e ((l i ne ~ in. readLi ne()) ! ~ null) byte[] data ~ line.getBytes(); packet.setOata(data); packet.setLength(data length); socket.send(packet); in.close(); socket.close(); Aufrufbeispiel Aufruf des Serverprogramms. start java -cp bin Receiver 50000 localhost 40000 Es können nur Datagramme von 1oca1hast mit Portnummer 40000 empfangen werden. Aufruf des Clientprogramms auf demselben Rechner; java -cp bin Sender 40000 localhost 50000 Der Socket des Clients ist an die Portnummer 40000 gebunden. Wird hier beim Aufruf statt 40000 z: B. 30000 angegeben, so ignoriert der Server die vom Client gesendeten Datagramme. 3.5 Online-Unterhaltung 3.5 109 Onllne·Unterhaltung Mit dem folge nde n Programm Talk kö nnen zwei Benut ze r an versch iedene n Rec hne rn ei ne Unte rhaltung o nline füh ren. ~ bl<-Hugo , ~ Ha l l o , wi e geht' s? 11 a n ke , g an z g u t! u , Bild 3.5 , I UtUerbaltung ,- " l*i T~ · EwoI onune- U , 11 - Dank e , g an z gut! » er rc , " .>0 ge ht ' s ? = Benutze r "H ugo " sitzt a m Rechner A OP-Adresse 10.108.105.95) , SZenario Benutzer "Emil" a m Rechner B (IP-Adresse 10.108.105.96) . Benutze r "H ugo" ruft das Programm wie folgt auf: java -c p bi n Talk Hugo 50000 10 .108 .105 .96 50000 Benutzer "Emil" gibt das folgende Kommando ein: java -cp bin Talk Emi 1 50000 10 .108 .105 .95 50000 Der UDP-Socket wird hier jeweils an die explizit vorg egebene lokal e Polt nummer 50000 (zwe ite r Aufrufparameter) ge bunden. Zum Test kann das Programm auch zweimal auf demselben Rec hner (localhost) gestartet we rden. Alle rdings mü ssen da nn die Po rtnumme rn unte rschiedlich sei n: j ava -cp bi n Talk Hugo 40000 localh os t 50000 jeve -cp bin Talk Emi 1 50000 localhost 4ססoo 3 110 Programm 33 lmport lmport import import import import import import import import import i mport i mport ja va ja va ja va ja va ja va ja va ja va ja va ja va java java java java import import import import import import ja vax.swing ja vax.swing javax.swing javax.swing javax.swing ja vax.swing Verbindungslose Kommunikation mit UDP awt Borderlayout; awt Container; awt Event Queue ; awt Fl owLayout ; awt Fant ; awt event.ÄctionEvent; awt event .Act i onLi ste ner ; awt event. WindowAdapter; awt.event. WindowEvent; i o.IOExcept i on; net.DatagramPacket; net.OatagramSocket; net. InetAddress; JButton: JFrame; JPanel; JScrollPane; JTextArea; JTextField; public class Talk imp le rrents Actionlistener, Runnable ( private static f inal int BUFS IZ E ~ 508; private DatagramSocket socket; prlvate DatagramPacket packetOut; private JTextField input; prl vate JTextArea output; public static voi d main(String [J args) { if (args,length !~ 4) ( System.err.prl ntln("java Talk <user> <localPort> " "<relTDte Host> <remotePort>"); + Systeniex i t.C l ): JFrame frame = new JFrame( ); try ( new Talk(args, frame); catch (Exception e) ( System,err,println(e); Systemex i t.C l ). fra rre pack(); fra me setVisible(true); public Talk(String[J args, JFrame fra me) throws Exception ( String user ~ args[OJ; int localPort ~ Int eger parse Int(args[IJ); 3.5 OnIine-Unterhaltung 111 String remoteHost ~ args[2J; int remotePort ~ Int eger .parse lnt (args [3J ) ; InetAddress.getByName( InetAddress remoteAddr remoteHost) ; ~ frame.setTitle("Talk "+ user); socket ~ new DatagramSocket(localPort); packetOut ~ new DatagramPacket(new byte[BUFSIZEJ. BUFSIZE. remoteAddr. remotePort); frame.addWindowListener(new WindowAdapter() ( public void windowClosing(WindowEvent e) { i f (socket ! ~ null) socket. cl ose () ; System. exi t( 0) ; } }) ; Contalner c JPanel panel frame.getContentPane(); = ~ new JPanel(new FlowLayout(FlowLayout.LEFT. 2. 2)); input ~ new JTextField(40); input. setF ont (new Font("11mospaced". Font. PLAI N. 18)); pane1. add(input) ; JButton send ~ new JButton("Senden"); send.addActionListener(this); pane1. add(send); c.add(panel. 8orderLayout.NORTH); output ~ new JTextArea(IO. 45); output.setFont(new Font("Monospaced". Font.PLAIN. 18)); output.setLineWrap(true); output.setWrapStyleWord(true); output.setEdi table(false); c.add(new JScrollPane(output). BorderLayout.CENTER); // Thread zum Empfangen von Nachrichten starten Thread t ~ new Thread(this); t.start(); public void run() ( OatagramPacket packetIn ~ new OatagramPacket( new byte[BUFSIZEJ. BUFSIZE); whi 1e (true) { try ( receive(packetIn); 112 3 Verbindungslose Kommunikation mit UDP catch (I OExcept i on e) ( break; prl vate vOl d recel ve(DatagramPacket packet ln) t hr ows IOExcept i on ( socket.recel ve(packet In); final String text ~ new String(packet ln getData(), 0, packet ln,ge tlength()); try ( Event Queue , i nvokel at er (new Runnable() ( public void run() ( output,append(text); output . append("ln"); } }) ; catch (Exception e) ( public void actionPerformed(ActionEvent e) { try ( byte[] data ~ input,getText(),getBytes(); packetOut.setData(data) ; packetOut,setlength(data,l ength); socket,send(packetOut); catch ( IOException ex) System,err,pr i ntln(ex); Im Konstruktor werden zunächst IP-Adressen bestimmt, der UDP-Socket an die vorgegebene lokale Portnummer gebunden und ein Paket zum Senden der eingegebenen Daten erstellt. Beim Schließen des Fensters wird der Socket geschlossen. Textfeld, Button und Textfläche werden erzeugt und platziert sowie das aktuelle Objekt als Acti onl i stener beim Button registriert. Schließlich wird ein Thread, der Datagramme empfängt (siehe run-Methode), erzeugt und gestartet. Innerhalb der run-Methode werden in einer Endlos-Schleife die Daten empfangen und in der Textfläche angezeigt. Die DatagramSocket-Methode recel ve blockiert so lange, bis ein Datagramm empfangen wurde, Die Ausgabe des Textes erfolgt in der runMethode eines Runnab1e-Objekts r, das mittels Event Queue , 3.6 Punkt-zu-Mehrpunkt-Verbindungen 113 lnvokeLater(r) an den Ereignis-Dispatcher, der für die Aktualisierung der Benutzungsoberfläche verantwortlich ist, zur Ausführung weitergeleitet wird. Beim Drücken des Buttons "Senden" werden die Daten des Eingabefeldes in einem Datagramm an die Zieladresse gesendet. 3.6 Punkt-zu-Mehrpunkt-Verbindungen Bisher haben wir in diesem Kapitel ausschließlich Punkt-zuPunkt-Verbindungen (Unicast) betrachtet. Unter Multicast versteht man eine übertragung von einem Teilnehmer zu einer Gruppe von Teilnehmern (Punkt-zu-Mebrpunkt-Verbindung). Der Vorteil dieses Verfahrens liegt darin. dass gleichzeitig Pakete über eine einzige Adresse an mehrere Teilnehmer gesendet werden. Die Vervielfältigung der Pakete findet nicht bereits beim Sender statt, sondern erst an jedem Verteiler auf dem übertragungsweg. So wird Multicasting insbesondere zur übertragung von Audio- und Videosträmen eingesetzt, um die Netzbelastung zu reduzieren. on e-to-many = Dalagramm ,ro ~ Multicast-Gruppe 228.5.6.7 Q~ Im Internet werden für das Multicasting die IP-Adressen der Klasse D verwendet 224.0.0.0 - 239.255.255.255 Eine Multicast-Gruppe wird durch eine Adresse dieses Bereichs (Multicast-Adresse) und eine UDP-Portnummer repräsentiert. Die Adresse 224.0.0.0 ist reserviert und sollte nicht benutzt werden. Teilnehmer können jederzeit einer Multicast-Gruppe beitreten oder diese wieder verlassen. Wird eine Nachricht an eine Multicast-Gruppe gesendet, erhalten alle Gruppenteilnehmer diese Nachricht, sofern sie sich im Time-to-Live-Bereich des Pakets befinden. Das Feld Time-ta-Live (TTL) im Header eines IP-Pakets gibt an, wie lange ein Paket im Internet verbleiben darf. Es handelt sich um einen Zähler, der von jedem Router, den das Paket passiert, um 1 dekrementiert wird. Bei einem Wert von 0 wird Bild 3,6.' Mu!ticasting 3 Verbindungslose Kommunikation mit UDP 114 das Paket zerstört. Die Reichweite der gesendeten Pakete kann also durch die Angabe des Time-to-Live-Wertes eingeschränkt werden. MulticastSocket Die Klasse ja va.net. Multi castSocket (Subklasse von DatagramSocket) wird zum Senden und Empfangen von MulitcastDatagrammen verwendet. void setTimeToLive( i nt ttl) throws IOExcept i on setzt den Time-To-Live-Wert. Zulässiger Wert, 0 <= ttl <= 255. Voreinstellung ist 1void joinGroup(lnetAddress mc ast addr ) throws IOExcept i on tritt der Multicast-Gruppe bei. voi d leaveGroup( lnetAddress mcastaddr) throws IOExcept i on verlässt die Multicast-Gruppe . Ein Client, der ein Datagramm an eine Multicast-Gruppe sendet, muss selbst nicht Teilnehmer dieser Gruppe sein. Programm 3.4 Sender Im folgenden Beispiel bilden zwei Receiver eine Multicast- Gruppe (IP-Adresse, 228.5.6.7, Portnummer. 50000). Ein Sender schickt in kurzen Abständen Nachrichten an diese Gruppe. lmport lmport lmport lmport ja va ja va ja va ja va net DatagramPacket; net DatagramSocket; net. InetAddress; util . Random; public class Sender ( private static final int BU FS IZ E ~ 508; pri vate stati c fi na1 i nt LOOPS ~ 10; public static voi d main(String [J args) throws Except i on ( String host ~ args[OJ; int port ~ Int eger .parsel nt (args[l J ) ; OatagramSocket socket ~ new DatagramSocket(); Inet Address addr ~ Inet Address .get ByName(host ); DatagramPacket packet = new DatagramPacket( new byte[BU FS IZ EJ. BU FS IZ E. addr. port ); for (int i ~ 0; i < LOOPS; i++) Random random = new Random (); int value = random.next Int () ; byte[J data ~ String. valueOf (value).getBytes (); packet.setOata(data); packet.setLength(data length); socket.send(packet); 3.6 Punkt-zu-Mehrpunkt-Verbindungen 115 Thread.sleep(3000); lmport java net.DatagramPacket; lmport java net.InetAddress; lmport java net MultlcastSocket; public class Receiver ( private static final int BUFSIZE Receiver ~ 508; public static void main(String[] args) throws Exception String id ~ args[O]; InetAddress group ~ InetAddress.getByName(args[I]); int port ~ Integer.parselnt(args[2]); System.out.prlntln("Recelver " + id); MulticastSocket socket ~ new MulticastSocket(port); socket. setTi !TeToli ve(I); / / begrenzt auf lokales Subnetz socket. j oi nGroup (group) ; OatagramPacket packetIn ~ new OatagramPacket( new byte[BUFSIZE]. BUFSIZE); whi 1e (true) ( socket.receive(packetIn); String received ~ new String(packetln getOata(). O. packetln.getlength()); System.out.println(received); Zum Testen auf einem lokalen Windows-Rechner muss das Test Netzwerk-Interface mit einer IP-Adresse konfiguriert sein. Ggf. sind Firewall-Einstellungen anzupassen. start java -cp bin Receiver I 228.5.6.7 50000 start java -cp bin Receiver 2 228.5.6.7 50000 java -cp bin Sender 228.5.6.7 50000 116 3 3.7 Verbindungslose Kommunikation mit UDP Aufgaben 1. Entwickeln Sie einen Server (Dayti rreSer ver) , der als Reaktion auf den Empfang eines "leeren" Datagramms die aktuelle Systemzeit in Form einer Zeichenkette an den Sender zurückschickt. Programmieren Sie für den Test auch einen passenden Client (Dayti rre Cl i ent), der maximal zwei Sekunden auf die Antwort des Servers wartet. 2, Ein Client (M2sswertCl i ent) sendet in Abständen von 5 Sekunden Zufallszahlen mit Zeitpunktangaben an den Server. Der Server (rvesswertServer) gibt diese Zahlen zusammen mit der IP-Adresse des Senders am Bildschirm aus. Beispiel, 10.108.105. 95 :39751 0:45:4648.72014957156734 10.108.105. 95 :39751 0:45:5148. 557565388620226 10.108.105. 95 :39751 0:45:56 70. 66274469656827 3. Ein Server (QuoteServer) liefert zufallsgesteuert Zitate. Alle Zitate befinden sich in einer Datei quotes.txt, die den folgenden Aufbau hat Zitat (eine Zeile) Autor des Zitats (eine Zeile) Zitat (eine Zeile) Autor des Zitats (eine Zeile) Erhält der Server ein "leeres" Datagramm, so bestimmt eine Zufallszahl, welches Zitat (mit Autor) an den Client gesendet wird. Programmieren Sie zum einen eine Anwendung mit grafischer Oberfläche (Quo teApp) und zum andem ein Applet (QuoteApp1et) zur Anzeige des angeforderten Zitats. 4. Erstellen Sie eine Variante des Programms 3.3 (Talk) für eine Gruppenkommunikation mit Hilfe des MulticastingVerfahrens aus Kapitel 3.6. Aufrufparameter sollen sein: User, Multicast-Adresse, Portnummer.