Heute gibt es kaum noch eine Anwendung ohne eine gewisse Netzwerkfunktionalität. Wie Sie ein einfaches Client/Server-Beispiel erstellen können – und das auch noch auf den verschiedensten Plattformen –, zeigt Ihnen dieses Kapitel.
25 Netzwerkprogrammierung und Cross–Plattform-Entwicklung
Die Netzwerkprogrammierung gehört nicht unbedingt zu den einfacheren Themen in der Programmierung. Auch wenn Ihnen dieses Kapitel den Eindruck verschafft, es sei alles nicht so schwer, sollten Sie sich nicht täuschen lassen: Sie erhalten hier lediglich einen Einblick in die Welt der Netzwerkprogrammierung. Allerdings erscheint es mir sehr wichtig, Ihnen diese Basis mitzugeben, da heutzutage kaum noch eine Anwendung ohne Netzwerkfunktionalität angeboten wird.
Sicherlich stellt sich zunächst die Frage, wie man die Netzwerkprogrammierung in einem Buch behandelt, das sich primär mit der Erstellung von portablen Programmen befasst. Prallen hier mit der Netzwerkprogrammierung unter MS-Windows und den UNIX-Varianten (Linux) nicht zwei verschiedene Welten aufeinander?
Im Verlaufe des Kapitels werden Sie merken, dass die grundlegenden Prinzipien dieselben sind – und die Funktionsnamen sind zum Teil sogar die gleichen. Und darum geht es auch im zweiten Teil dieses Kapitels, bei der Cross-Plattform-Entwicklung. Dabei werden Sie erfahren, wie Sie sinnvoll portable Headerdateien bzw. Bibliotheken erstellen können, die auf den verschiedensten Plattformen ausführbar sind (hier MS-Windows und Linux/UNIX) – natürlich wiederum anhand von Beispielen zur Netzwerkprogrammierung.
Hinweis |
Um im Rahmen dieses Buches zu bleiben, gebe ich hier nur eine Einführung in die Netzwerkprogrammierung. Bei dem Thema wäre es sogar angemessen, sich extra Literatur dazu anzuschaffen. |
25.1 Begriffe zur Netzwerktechnik 

Bevor ich Sie in die Netzwerkprogrammierung einführe, möchte ich Ihnen hier noch einige Begriffe der Netzwerktechnik etwas näherbringen, damit Sie anschließend bei der Programmierung nicht ins Straucheln geraten. Sollten Sie mit den Begriffen der Netzwerktechnik bereits vertraut sein, können Sie diesen Abschnitt selbstverständlich überfliegen.
25.1.1 IP-Nummern 

Die IP-Nummer (IP – Internet Protokoll) ist mit einer Telefonnummer vergleichbar. Unter dieser Nummer sind Sie im Internet für alle anderen Teilnehmer erreichbar. Daher ist es auch verständlich, dass diese Nummer eindeutig sein muss, sodass keine Adresskonflikte auftreten können.
Statische und dynamische IP-Nummern
Bei den IP-Nummern unterscheidet man (sofern man von einem Unterschied sprechen kann) zwischen einer statischen und einer dynamischen IP-Nummer. Rechner, die ständig im Internet sind, um etwa einen bestimmten Service anzubieten, benötigen meistens eine statische IP-Nummer. Man spricht von einer statischen IP-Nummer, wenn einem Rechner einmal eine Nummer zugeteilt wird und sich diese anschließend nicht mehr ändert. Natürlich können Sie sich auch eine eigene IP-Nummer geben lassen (beispielsweise um einen eigenen Webserver zu betreiben). Dazu müssen Sie sich über einen Internet Provider oder besser gleich über das Network Information Center (NIC) eine solche Nummer zuteilen lassen. Für Privatpersonen bzw. mittelständische Firmen lohnt sich dies allerdings recht selten – da eine feste IP-Nummer auch ihren Preis hat.
Gewöhnlich wird Ihnen, wenn Sie sich ins Internet einwählen, jedes Mal eine neue dynamische IP-Adresse erteilt. Sie wählen sich praktisch ins Internet ein und Ihr Internet Service Provider teilt Ihnen so eine dynamische IP-Adresse zu. Neben dem geringeren Verbrauch von IP-Adressen wird auch der Admin-Aufwand erheblich verringert. Dies trifft besonders bei größeren lokalen Netzwerken zu. Hierbei muss der Admin nicht jede einzelne statische IP-Adresse ins Netzwerk integrieren, sondern meistens übernimmt eine Software die Verteilung der dynamischen IP-Adressen.
IPv4- und IPv6-Nummern
Im Augenblick setzen sich die IP-Nummern (IPv4) noch aus vier Zahlen (32 Bit) zwischen 0 und 255 zusammen. Dadurch sind mit IPv4 Adressierungen zwischen 0.0.0.0 und 255.255.255.255 möglich – was etwa 4 Milliarden Adressen wären. Allerdings nur theoretisch – da diverse Nummern, beispielsweise mit der Endung 0 und 255, für andere Zwecke vergeben sind. Und 4 Milliarden IP-Adressen sind in der Tat nicht viele – wenn man diese Zahl mit der Weltbevölkerung vergleicht. Somit musste eine andere Lösung gefunden werden – die auch schon längst mit IPv6 gefunden wurde. In IPv6 sind die Adressen 128 Bit lang, anstatt der 32 Bit in IPv4. Damit lassen sich natürlich erheblich mehr IP-Adressen darstellen.
IPv6 ist allerdings noch nicht eingeführt und immer noch für unbestimmte Zeit Zukunftsmusik. Wenn IPv6 eingeführt wird, werden Sie sich auch an eine andere Schreibweise gewöhnen müssen, die auf den ersten Blick ein wenig komplexer erscheint. Schreibt man beispielsweise eine IPv6-Adresse vollständig aus, ergeben sich sieben Doppelpunkte getrennt durch Hexadezimalzahlen:
2ffd:345:34b:33:432:e23:a:2
Diese Schreibweise kann durch die Zusammenfassung von Nullen noch vereinfacht werden. So kann beispielsweise eine Gruppe von aufeinanderfolgenden Nullen durch zwei Doppelpunkte (::) angegeben werden. Dies ist beispielsweise auch nötig bzw. der Fall, wenn die Kompatibilität zu IPv4-Adressen gewahrt werden muss. Da beispielsweise bei einer IPv4-Adresse, die in IPv6 konvertiert wird, die ersten sechs Gruppen mit Nullen beziffert sind (IPv4: xxx.xxx.xxx.xxx konvertiert zu IPv6: 0:0:0:0:0:0:xxxx:xxxx), kann man es sich auch hier mit der Doppelpunktregelung einfacher machen (0:0:0:0:0:0:xxxx:xxxx; Gruppe von Nullen durch :: ersetzen ::xxxx:xxxx). Und damit man bei der Konvertierung nicht dauernd auch noch den hexadezimalen Wert der IPv4-Adresse zur IPv6-Adresse umrechnen muss (oder errechnen lässt), ist es auch erlaubt, dass die letzten beiden Ziffern dezimal (also aus den vier Zahlen wie in IPv4) angegeben werden können (also als 0:0:0:0:0:0:xxx.xxx.xxx.xxx oder auch als ::xxx.xxx.xxx.xxx).
25.1.2 Portnummer 

Bei den Internetprotokollen TCP/IP und UDP/IP sind neben den IP-Nummern, mit denen ein Rechner spezifiziert wird, auch noch sogenannte Portnummern (16 Bit lang; 0 bis 65535) vorhanden. Mit den Portnummern wird ein bestimmter Service (Dienst) auf dem Rechner spezifiziert. Jeder Service (Dienst) hat dabei gewöhnlich eine eigene Portnummer. Die bekannteste Portnummer z. B. dürfte 80 (HTTP-Dienst) sein: Über diesen Port unterhält sich gewöhnlich der Webserver mit dem Webbrowser. Entsprechend der Portnummer reagiert also auch der Rechner mit einem entsprechenden Dienst und dem damit verknüpften Protokoll.
Bei Firewalls lassen sich die Portnummern verwenden, um gewisse Nachrichten herauszufiltern. Ebenfalls lassen sich dabei bestimmte Dienste auf dem Rechner sperren, indem einfach entschieden wird, welche Ports durchgelassen werden und welche nicht. Man kann sich die Ports gern als Türen vorstellen – lässt man andauernd die Tür offen stehen, braucht man sich nicht über ungebetene Gäste wundern.
Selbstverständlich sind die Ports auch (teilweise) standardisiert. Besonders die ersten 1023 Portnummern werden beispielsweise von der IANA (Internet Assigned Numbers Authority) kontrolliert und zugewiesen. Unter Linux/UNIX können diese ersten 1023 Portnummern in der Regel meistens nur durch den Superuser verwendet werden. Hier finden sich die Portnummern vieler Standard-Anwendungen wieder. Beispielsweise wird FTP über Port 21 abgewickelt, TELNET über Port 23 oder der Internetverkehr (HTTP) über Port 80. Natürlich sind die Portnummern unter 1024 auch ein beliebtes Ziel für Hacker.
25.1.3 Host- und Domainname 

Zwar wissen Sie jetzt, dass im Internet alles über IP-Nummern erreichbar ist, aber wenn Sie sich mit diesen Nummern durchs WWW hangeln müssten, wäre das Internet wohl heute nicht so erfolgreich. Deshalb wird an die Nummern noch zusätzlich ein Name vergeben, der aus dem Host- und dem Domainnamen (und eventuell einer Top-Level-Domain; TLD) besteht (hostname.domainname.tld; beispielsweise www.pronix.de).
Der Domainname ist der Name, mit dem Sie eine Webseite (beispielsweise pronix.de) im Internet ansprechen. Ein Domainname wird von hinten nach vorne aufgelöst. Somit steht das de für die Top-Level-Domain (wie der Name sagt, das, was ganz vorne steht). Die Top-Level-Domain bezeichnet die Herkunft und/oder die Zugehörigkeit (.com, .gov, .net etc.), in unserem Beispiel de für Deutschland. Nach der Top-Level-Domain folgt weiter links der eigentliche Domainname, der im Beispiel pronix lautet.
Der Hostname ist somit die niedrigste Instanz eines Domainnamens, da dieser ja von hinten nach vorne aufgelöst wird. Der Hostname ist somit der erste Teil in der Leseweise. Gewöhnlich lautet im Internet der Hostname www (www.pronix.de) – allerdings spricht nichts dagegen, den Host auch anders zu benennen. Es wird nämlich nur empfohlen, weil sich viele Anwender an das www gewöhnt haben. Genauso gut könnten Sie auch abc.pronix.de verwenden.
25.1.4 Nameserver 

Einfach ausgedrückt ist ein Nameserver ein Rechner, der für die Umsetzung von Rechnernamen in IP-Nummern verantwortlich ist. Im Internet beispielsweise ist dies mit einem Telefonbuch vergleichbar, in dem der Name des Teilnehmers in die Telefonnummer aufgelöst wird. Der Dienst, der Ihnen diese Arbeit im Internet abnimmt, wird als Domain Name System (DNS) bezeichnet. Bei kleineren Netzwerken wie einem Intranet, werden die lokalen IP-Nummern meistens in Form einer Tabelle in einer Datei hinterlegt.
25.1.5 Das IP-Protokoll 

Das IP-Protokoll ist dafür verantwortlich, dass die Datenpakete von einem Sender über mehrere Netze zum Empfänger transportiert werden. Die Übertragung des IP-Protokolls findet paketorientiert und verbindungslos statt. Es wird dabei nicht garantiert, dass die Pakete in der richtigen Reihenfolge oder überhaupt beim Empfänger ankommen. Ebenfalls liefert es keine Empfangsbestätigung vom Empfänger an den Sender zurück. Die maximale Länge eines IP-Paketes ist auf 65.535 Bytes beschränkt. Da das IP-Protokoll auch für das IP-Routing durch ein Netzwerk verantwortlich ist, kann dieses Protokoll die einzelnen Stationen auch anhand der IP-Adresse identifizieren. Da es ja keine Garantie gibt, dass die Daten ans Ziel gelangen, gibt es im IP-Header des IP-Paketes ein Time-to-Live-Feld (TTL), in dem die Lebensdauer eines Datagramms (hier des Pakets) festgelegt wird. Das TTL-Feld sorgt dafür, dass die Datenpakete nicht unendlich durch das Netz irren und den Datenverkehr belasten. Ist die im TTL-Feld angegebene Lebensdauer abgelaufen, wird das Datenpaket verworfen.
Abbildung 25.1 Das IP-Protokoll und die assoziierten Verbindungen
25.1.6 TCP und UDP 

Aufbauend auf das IP-Protokoll gibt es zwei wichtige Transportprotokolle: TCP/IP (TCP – Transmission Control Protocol) und UDP/IP (UDP – User Datagram Protocol). Beide Protokolle sind auf der Transport-Ebene angesiedelt.
Der Vorteil von TCP ist, dass eine zuverlässige Datenübertragung garantiert wird. Dabei wird beispielsweise sichergestellt, dass ein Paket, das nach einer gewissen Zeit nicht beim Empfänger angekommen ist, erneut gesendet wird. Ebenso garantiert TCP, dass die Datenpakete auch in der Reihenfolge geliefert werden, in der sie losgeschickt wurden. Zusammengefasst erhalten Sie beim TCP-Protokoll eine Ende-zu-Ende-Kontrolle (Peer-to-Peer), ein Verbindungsmanagement (nach dem sogenannten Handshake-Prinzip), eine Zeitkontrolle, eine Flusskontrolle sowie eine Fehlerbehandlung der Verbindung. Man spricht bei TCP von einem verbindungsorientierten Transportprotokoll.
Das UPD-Protokoll hingegen verwendet einen verbindungslosen Datenaustausch zwischen den einzelnen Rechnern. Mit UDP haben Sie in Ihren Anwendungen die direkte Möglichkeit, Datagramme zu senden. Allerdings gibt es keine Garantie, dass ein Datagramm beim Empfänger abgeliefert wird. Ebenso wenig ist es gegeben, dass die Datagramme in der richtigen Reihenfolge ankommen (es ist sogar möglich, dass Datagramme mehrfach ankommen). Der Vorteil davon, dass bei UDP weniger Verwaltungsaufwand betrieben werden muss, ist natürlich ein höherer Datendurchsatz, der mit TCP nicht möglich ist. UDP ist beispielsweise recht interessant für Videoübertragung oder bei Netzwerkspielen. In diesen Anwendungsbereichen ist es nicht so schlimm, wenn das eine oder andere Datenpaket mal nicht ankommt. Die UDP-Strategie kann man gern mit dem Motto »Erst schießen, dann fragen« vergleichen.
Hinweis |
Vorwiegend wird in diesem Buch das gängigere TCP-Protokoll beschrieben – aber dennoch wird gegebenenfalls auf die Unterschiede zum UDP-Protokoll eingegangen. Allerdings sei gesagt, dass die Unterschiede beider Protokolle bei ihrer Verwendung nicht allzu groß sind. |
25.1.7 Was sind Sockets? 

Ein Socket ist eine bidirektionale (Vollduplex-)Software-Struktur, die zur Netzwerk- oder Interprozesskommunikation verwendet wird. Somit ist ein Socket eine Schnittstelle zwischen einem Prozess (Ihrer Anwendung) und einem Transportprotokoll, was meistens das TCP- oder UDP-Protokoll ist.
In den RFCs ist ein Socket als ein 5-Tupel aus Ziel- und Quell-IP-Adresse, Ziel- und Quell-Port und dem Netzwerkprotokoll beschrieben. Sockets werden in UDP und TCP verwendet.
RFC |
RFCs (Requests for Comments) sind eine Reihe von technischen und organisatorischen Dokumenten zum Internet (ursprünglich ARPANET), die 1969 begonnen wurde. Mehr dazu finden Sie unter der offiziellen Webseite http://www.rfc-editor.org/. |
Seit 1983 verwendet BSD die Netzwerk-Sockets in seiner Berkeley Sockets API. Linux, Solaris und viele andere UNIX-Varianten verwenden ebenfalls die BSD-Sockets. Der Zugriff auf ein Socket erfolgt ähnlich wie auf Dateien mit einem Filedeskriptor – nur mit dem Unterschied, dass es bei Sockets nicht um Dateien geht, sondern um Kommunikationskanäle.
MS-Windows verwendet eine ähnliche API wie in den Berkeley Sockets, die Windows Sockets (kurz Winsock).
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.