4 TCP/IP für Programmierer

Zum vorigen Kapitel Zum Inhaltsverzeichnis Zum nächsten Kapitel


Wir wollen uns die einfache Aufgabe stellen, eine kurze Zeichenkette "über TCP/IP" von einem Computer A an einen anderen Computer B zu schicken. Dazu brauchen wir auf dem Computer A ein Programm, das die Zeichenkette entgegennimmt und an den Computer B sendet. Auf dem Computer B muss zur gleichen Zeit ein Programm laufen, das auf ankommende Zeichenketten wartet, sie gegebenenfalls entgegennimmt und anzeigt. Aus dieser kurzen Beschreibung ist ersichtlich, dass das Programm auf dem Computer A vom Typ eines "Clients" ist, wohingegen auf dem Computer B ein "Server" läuft.

Zur Realisierung von Client- und Server-Programmen bedient man sich sogenannter "Sockets". "Socket" ist das englische Wort für "Steckdose", und es gibt diese Steckdose in zwei Varianten: als "Client-Socket" und als "Server-Socket". Man kann sich diese beiden Geräte durch eine Leitung verbunden denken, womit man ein Bild bekommt, das die Wirkungsweise schon ziemlich genau trifft: unsere Daten werden in die erste Steckdose (vom Typ ClientSocket) hingesteckt, laufen dann über ein mehr oder weniger verborgenes Kabel, um an dessen Ende an einer zweiten Steckdose (vom Typ ServerSocket) wieder ans Tageslicht zu kommen.

Zwei entsprechende Komponenten gehören zum Lieferumfang vieler Delphi-Editionen, nämlich TServerSocket und TClientSocket. Diese Komponenten sind die elementaren Werkzeuge, mit deren Hilfe ein Datentransport über das TCP/IP-Protokoll implementiert werden kann. Die verschiedenen Versionen von Delphi unterscheiden sich deutlich im Umfang der für die Netzwerk-Programmierung bereitgestellten Werkzeuge, aber diese elementaren "Sockets" sind in recht vielen Delphi-Versionen verfügbar. Gelegentlich ist jedoch die zugehörige Dokumentation äußerst spartanisch, oder sie fehlt sogar komplett. Daher folgt hier eine kurze Beschreibung der für uns wichtigsten Eigenschaften und Ereignisse dieser Komponenten:

Eigenschaften
Methoden
Bedeutung für
TClientSocket
TServerSocket
Active : Boolean ist genau dann True, wenn eine aktive TCP-Verbindung über diesen Socket besteht
Address : String enthält die TCP/IP-Adresse des Servers, der angesprochen werden soll
{nicht vorhanden}
Port : Integer enthält den Port des Servers, über den der Dienst angesprochen werden soll enthält den Port, über den der Dienst zur Verfügung gestellt wird
Socket : TCustomWinSocket stellt Eigenschaften und Prozeduren für die eigentliche TCP/IP-Transport-Funktionalität bereit:
z.B. LocalAddress, LocalPort, RemoteAddress, RemotePort
z.B. SendText(s: String)
diese Prozedur sendet den übergebenen String s an den Server
z.B. ReceiveText: String
diese Funktion gibt den vom Client geschickten String an das aufrufende Programm zurück
Open lokalisiert den Server, stellt die Verbindung zu ihm her und schaltet Active auf True schaltet den Server auf "Verbindungsbereitschaft" und Active auf True
Close unterbricht die Verbindung(en) und schaltet Active auf False

Zunächst fällt auf, dass die beiden Komponenten TServerSocket und TClientSocket sehr ähnlich aufgebaut sind. Tatsächlich stammen sie von einem gemeinsamen Vorfahren ab, nämlich TCustomSocket. Weitere netz-relevante Gemeinsamkeiten (wie z.B. Service oder ThreadCacheSize) dienen der bequemeren Handhabung und der Erhöhung der Betriebssicherheit; wir können sie hier aber unbeachtet lassen. Ein paar Bemerkungen zum Betrieb der Komponenten:

Auch wenn diese Beschreibung zunächst abschreckend kompliziert wirkt, sollten Sie sich nicht entmutigen lassen! Der Sinn und Zweck der Komponenten TServerSocket und TClientSocket ist es, dem Programmierer die Benutzung des TCP/IP-Protokolls zu erleichtern, und Sie dürfen sicher sein, dass der Weg zu diesem Ziel ohne diese Komponenten noch um einiges steiniger wäre!




Aufgaben:


  1. Erst verbinden....

    Arbeiten Sie in Zweiergruppen, jeder an einem eigenen Rechner!
    Erstellen Sie auf dem einen Rechner ein einfaches Server-Programm, am anderen ein einfaches Client-Programm. Benutzen Sie dazu die oben vorgestellten Komponenten TServerSocket und TClientSocket. Jedes dieser Programme soll die Aktivitäten seiner Socket-Komponente in einem Memo-Feld protokollieren, indem alle (obengenannten) Ereignisse dieser Komponenten bei ihrem Eintreten eine entsprechende Meldung in diesem Memo-Feld ablegen. Versuchen Sie zunächst nur, vom Client aus eine TCP/IP-Verbindung zum Server zu erstellen. Kontrollieren Sie den Erfolg Ihrer Bemühungen gemäß der obigen Beschreibung! Erst wenn die Verbindung "steht", hat es Zweck, mit der nächsten Aufgabe fortzufahren!
    [Lösungsvorschlag]


  2. ....dann senden!

    Wenn Ihr "Client-Server-Gespann" die TCP/IP-Verbindung aus der ersten Aufgabe erfolgreich einrichten kann, dann erweitern Sie die Programme, damit sie nun die Verbindung auch wirklich zur Datenübertragung benutzen:

    • Client-Programm:
      Fügen Sie ein Edit-Feld und einen "Senden"-Knopf hinzu, in dessen OnClick-Ereignis der aktuelle Text aus dem Edit-Feld an den Server gesendet wird.
    • Server-Programm:
      Ergänzen Sie das Ereignis OnClientRead so, dass es den vom Client gesendeten String in dem Memo-Feld ausgibt.

    Testen Sie Ihr "Client-Server-Gespann" ausführlich! Wie verhält es sich, wenn der Client unerwartet den Betrieb einstellt, was passiert, wenn der Server "aussteigt"?
    [Lösungsvorschlag]


  3. Ein TCP/IP-Telephon

    In der vorigen Aufgabe fand der Datentransport nur in einer Richtung statt. Nun wollen wir einen bidirektionalen Datenkanal modellieren:
    Schreiben Sie ein Programm, das Telephon-Funktionalität auf TCP/IP-Basis darstellt. Wenn zwei verschiedene Instanzen dieses Programms auf zwei verschiedenen Computern laufen, dann soll von einem Computer aus ein "Gespräch" eröffnet werden können, wobei Strings in beide Richtungen ausgetauscht werden können.

    Einige Tips dazu:
    • Das Programm muss dazu sowohl Server- als auch Client-Funktionalität beinhalten.
    • Es muss zwei verschiedene Initialisierungs-Modi geben: "Anrufen" und "Angerufen werden".
    • Nach der Initialisierung eines "Gesprächs" sollten die beiden kommunizierenden Programme jedoch auf die gleiche Weise arbeiten. Insbesondere soll das Gespräch von jedem der beiden Partner beendet werden können.
    • Während eines laufenden Gesprächs soll kein zweites Gespräch angenommen oder gestartet werden können. Berücksichtigen Sie dies durch eine entsprechende dynamische Gestaltung der Programm-Oberfläche!

    Es gibt viele verschiedene Möglichkeiten, solch ein Programm zu realisieren, und es werden Ihnen mit Absicht nun keine weiteren Vorschriften gemacht. Bemühen Sie sich aber bei der Realisierung dieses durchaus anspruchsvollen Projekts um eine übersichtliche Programmierung, so dass Sie eine echte Chance haben, Ihren Programmtext auch in zwei Wochen noch zu verstehen!
    [Lösungsvorschlag]







Zum vorigen Kapitel Zum Inhaltsverzeichnis Zum nächsten Kapitel