Begleitmaterial Abitur 2024

Anbieten von Diensten mittels Server

An dieser Stelle bietet es sich an, von oben nach unten (Top-Down) vorzugehen d.h.

  1. Analyse vorgegebener Implementationen einfacher Server
  2. Modellierung und Implementierung eigener Server

Mithilfe der Java-Klasse Server lassen sich sehr einfach Server implementieren, d.h. Programme, die im Netzwerk Dienste für Clients zur Verfügung stellen.

Dokumentation der Klasse Server

Objekte von Unterklassen der abstrakten Klasse Server ermöglichen das Anbieten von Serverdiensten, so dass Clients Verbindungen zum Server mittels TCP/IP- Protokoll aufbauen können. Zur Vereinfachung finden Nachrichtenversand und - empfang zeilenweise statt, d. h., beim Senden einer Zeichenkette wird ein Zeilentrenner ergänzt und beim Empfang wird dieser entfernt. Verbindungsannahme, Nachrichtenempfang und Verbindungsende geschehen nebenläufig. Auf diese Ereignisse muss durch Überschreiben der entsprechenden Ereignisbehandlungsmethoden reagiert werden. Es findet nur eine rudimentäre Fehlerbehandlung statt, so dass z.B. Verbindungsabbrüche nicht zu einem Programmabbruch führen. Einmal unterbrochene oder getrennte Verbindungen können nicht reaktiviert werden.

  • Server(int pPort)

Ein Objekt der Klasse Server wird erstellt, das über die angegebene Portnummer einen Dienst anbietet an. Clients können sich mit dem Server verbinden, so dass Daten (Zeichenketten) zu diesen gesendet und von diesen empfangen werden können. Kann der Server unter der angegebenen Portnummer keinen Dienst anbieten (z.B. weil die Portnummer bereits belegt ist), ist keine Verbindungsaufnahme zum Server und kein Datenaustausch möglich.

  • boolean isOpen() Die Anfrage liefert den Wert true, wenn der Server auf Port pPort einen Dienst anbietet. Ansonsten liefert die Methode den Wert false.
  • boolean isConnectedTo(String pClientIP, int pClientPort) Die Anfrage liefert den Wert true, wenn der Server auf Port pPort einen Dienst anbietet. Ansonsten liefert die Methode den Wert false.
  • void send(String pClientIP, int pClientPort, String pMessage) Die Nachricht pMessage wird – um einen Zeilentrenner erweitert – an den durch pClientIP und pClientPort spezifizierten Client gesendet. Schlägt der Versand fehl, geschieht nichts.
  • void sendToAll(String pMessage) Die Nachricht pMessage wird – um einen Zeilentrenner erweitert – an alle mit dem Server verbundenen Clients gesendet. Schlägt der Versand an einen Client fehl, wird dieser Client übersprungen.
  • void closeConnection(String pClientIP, int pClientPort) Die Verbindung des Servers zu dem durch pClientIP und pClientPort spezifizierten Client wird getrennt. Zuvor wird die Methode processClosingConnection mit IP-Adresse und Port des jeweiligen Clients aufgerufen. Ist der Server nicht mit dem in der Parameterliste spezifizierten Client verbunden, geschieht nichts.
  • void close() Alle bestehenden Verbindungen zu Clients werden getrennt und der Server kann nicht mehr verwendet werden. Ist der Server bereits vor Aufruf der Methode in diesem Zustand, geschieht nichts.
  • void processNewConnection(String pClientIP, int pClientPort) Diese Ereignisbehandlungsmethode wird aufgerufen, wenn sich ein Client mit IP- Adresse pClientIP und Portnummer pClientPort mit dem Server verbunden hat. Die Methode ist abstrakt und muss in einer Unterklasse der Klasse Server überschrieben werden, so dass auf den Neuaufbau der Verbindung reagiert wird. Der Aufruf der Methode erfolgt nicht synchronisiert.
  • void processMessage(String pClientIP, int pClientPort, String pMessage) Diese Ereignisbehandlungsmethode wird aufgerufen, wenn der Server die Nachricht pMessage von dem durch pClientIP und pClientPort spezifizierten Client empfangen hat. Der vom Client hinzugefügte Zeilentrenner wurde zuvor entfernt. Die Methode ist abstrakt und muss in einer Unterklasse der Klasse Serverüberschrieben werden, so dass auf den Empfang der Nachricht reagiert wird. Der Aufruf der Methode erfolgt nicht synchronisiert.
  • void processClosingConnection(String pClientIP, int pClientPort) Sofern der Server die Verbindung zu dem durch pClientIP undpClientPort spezifizierten Client trennt, wird diese Ereignisbehandlungsmethode aufgerufen, unmittelbar bevor die Verbindungstrennung tatsächlich erfolgt. Wird die Verbindung unvermittelt unterbrochen oder hat der in der Parameterliste spezifizierte Client die Verbindung zum Server unvermittelt getrennt, erfolgt der Methodenaufruf nach der Unterbrechung/Trennung der Verbindung. Die Methode ist abstrakt und muss in einer Unterklasse der Klasse Server überschrieben werden, so dass auf das Ende der Verbindung zum angegebenen Client reagiert wird. Der Aufruf der Methode erfolgt nicht synchronisiert.

Hinweis: Bei den folgenden Beispielen enthält das Paket netzklassen, die „Abiturklassen“ Server, Client, Connection und List. Diese müssen importiert werden, wenn sie verwendet werden sollen.

import netzklassen.Server;
public class EchoServer extends Server {
    public EchoServer() {
        super(7);
        System.out.println("Server gestartet");
    }

    public  void processNewConnection(String pClientIP, int pClientPort) {
    }

    public void processMessage(String pClientIP, int pClientPort, String pMessage) {
        send(pClientIP, pClientPort, pMessage);
    }
    public void processClosingConnection(String pClientIP, int pClientPort) {
    }
} 

Erläuterung Die Klasse Echoserver importiert die Klasse Server aus dem Paket netzklassen (Zeile 1). Echoserver ist eine Unterklasse der abstrakten Klasse Server (Zeile 2). Der Konstruktor ruft den Konstruktor der Klasse Server auf mit dem Port, auf dem der Dienst stattfindet (Zeile 4). Beim Echoserver ist das standardmäßig Port 7. Damit der Benutzer weiß, dass der Server erfolgreich gestartet wurde, wird eine entsprechende Meldung in die Konsole geschrieben. Die drei abstrakten Methoden processNewConnection, processMessage und processClosingConnection müssen überschrieben werden. Sie werden automatisch ausgeführt, sobald sich ein Client angemeldet hat, bzw. eine Nachricht von einem Client beim Server eingegangen ist, bzw. sich ein Client abgemeldet hat. Der Client ist vom Server über die jeweils als Parameter übergebene IP-Adresse und den Port des Clients eindeutig zu identifizieren. Beim Echoserver enthält lediglich die Methode processMessage eine Anweisung. Der Server sendet mit der Methode send an den Client den empfangenen Text zurück (Zeile 10). Der Server startet, sobald ein Objekt der Klasse EchoServer generiert wird. Wenn mit dem weiter oben beschriebenen Programm EchoClient eine Verbindung auf Port 7 zum Echoserver aufgebaut wird und eine Nachricht an den Server versendet wird, schickt der Server diese unverändert zurück. Wenn Server und Client auf demselben Rechner ausgeführt werden, erfolgt die Verbindung über die IP-Adresse „127.0.0.1“ ansonsten über die IP-Adresse des Rechners, auf dem der Server läuft.

Aufgaben

  1. Entwickle einen Daytime-Server.
  2. Entwickle einen QOTD-Server, der aus einer Liste mit Zitaten berühmter Persönlichkeiten zufällig das „Zitat des Tages“ an einen QOTD-Client sendet.
  3. Entwickle einen Geburtstagserver, der nach Angabe des Gebutrtstags zurückgibt wieviele Tage es noch bis zum nächsten Geburtstag dauert.
  4. Entwickle eine Zahlenratenserver, bei dem du dich zuerst anmelden musst, dann eine Zahl zwischne 0-100 raten musst. Abschließend verabschiedet sich der Server und beendet die Verbindung. Halte beispielhaft die Kommunikation in allen 3 Phasen fest. Halte das Protokoll tabellarisch fest!