Die Zeitdienste und ein eigener Server und Client

Ein Zeit-Server bietet Clients immer die aktuelle Server-Uhrzeit an. Wir halten uns hier an das Daytime Protocol, welches im RFC 867 beschrieben ist. Ein Server lauscht auf Port 13 nach UDP-Paketen10 und sendet dann die Antwort an den Sender, dessen Adresse er aus dem Paket nimmt. Im Gegensatz zu unseren bisher geschriebenen Programmen muss der Client erst ein Paket aufbauen, es senden und dann auf die Antwort warten. Der Server erwartet jedoch kein spezielles Anfrageformat. Er reagiert auf einen beliebigen Inhalt, da er diesen ohnehin verwirft. Die Zeichenkette vom Server muss kein spezielles Format besitzen, doch bietet sich hier eine Zeichenkette mit dem Format »Wochentag, Monat, Tag, Jahr, Zeitzone« an.

Da Client und Server ziemlich ähnlich aufgebaut sind, ist es eigentlich egal, mit welchem Teil wir beginnen. Sie unterscheiden sich wenig, da beide Daten empfangen und senden. Wenn wir einen Client für Zeitdienste programmieren, können wir den eingebauten Daytime-Server nutzen. Unter Unix ist dieser schon vorinstalliert. Unter Windows müssen wir den Dienst erst mit dem Zusatzprogramm Uatime32 aus den Socket-Programmen starten. Da wir aber gleich selber einen Server programmieren werden, lässt sich zum Testen auch ein Kapitel weiter schauen.

Die folgende Implementierung zeigt, wie ein Zeit-Server angesprochen wird. Dazu wird zunächst ein leeres Paket als Anfrage an den Server gesendet. Anschließend wird mit receive() auf das hereinkommende Paket gewartet. Wenn dieses kommt, dann liefert getData() eine Zeichenkette mit der Zeit.

import java.net.*;
class UDPTimeClient
{
  public static void main( String args[] )
  {
    try
    {
      DatagramPacket packet;
      while ( true )
      {
        // zunächst die Anfrage an den Server
        byte data[] = new byte[1024];
        InetAddress ia = InetAddress.getByName( "localhost" );
        packet = new DatagramPacket( data, data.length, ia, 13 );
        DatagramSocket toSocket = new DatagramSocket();
        toSocket.send( packet );
        // Jetzt vom Server was empfangen
        DatagramSocket fromSocket = toSocket;
        //new DatagramSocket();
        packet = new DatagramPacket( data, data.length );
        fromSocket.receive( packet );
        String s = "Server" + //packet.getAddress() +
                   " am Port " + packet.getPort() +
                   " gibt mit die Zeit "+
                   new String( packet.getData() );
        System.out.println( s );
        fromSocket.close();
        Thread.sleep( 1000 );
      }
    }
    catch ( Exception e )
    {
      System.out.println( e );
    }
  }
}

Der Server liest aus dem Paket die IP-Adresse und Port-Nummer des Senders heraus und schickt ein Paket mit einer Zeiteinheit zurück. Das nachfolgende Programm wartet auf dem Port auf eine Anfrage und gibt die aktuelle Zeit einfach aus.

import java.net.*;
import java.util.*;
public class UDPTimeServer
{
  public static void main( String args[] )
  {
    try
    {
      byte data[] = new byte[ 1024 ];
      DatagramPacket packet;
      DatagramSocket socket = new DatagramSocket( 13 );
      while ( true )
      {
        // Auf Anfrage warten
        packet = new DatagramPacket( data, data.length );
        socket.receive( packet );
        // Empfänger auslesen, aber Paketinhalt ignorieren
        InetAddress adress = packet.getAddress();
        int         port   = packet.getPort();
        System.out.println( "Anfrage von " + packet.getAddress() +
                            " am Port " + packet.getPort() );
        // Paket für Empfänger zusammenbauen
        String s = new Date().toString() + "\n";
        s.getBytes( 0, s.length(), data, 0 );
        packet = new DatagramPacket(data,data.length,adress,port);
        socket.send( packet );
        Thread.sleep( 1000 );
      }
    }
    catch ( Exception e )
    {
      System.out.println( e );
    }
  }
}