SSL/TLS-Netzwerkprogrammierung mit Boost.Asio, Teil 1: Grundlagen

Know-how  –  12 Kommentare
Anzeige

Im Umfeld von C++ verspricht Boost.Asio, eine einfache, plattformübergreifende Möglichkeit zur Netzwerkprogrammierung zu sein. Dazu gehört auch das Absichern der Verbindungen mit SSL beziehungsweise TLS.

Seit der Artikelreihe auf heise Developer zur OpenSSL-Programmierung in C++ hat sich vieles getan. Die Sprache C++ und die verfügbaren Libraries wie Boost haben sich enorm weiterentwickelt.

Wie in der ursprünglichen Reihe zur OpenSSL-Programmierung kommt auch diesmal das WOPR-Beispiel zum Einsatz. Die Hommage an den Film "War Games" implementiert nun in Version 3.00 den mehr oder weniger logischen Dialog zwischen dem Terminal und dem Server aus dem Film. Damit lassen sich einfache Befehle an den Server übermitteln, der seinerseits darauf reagiert. Auf die Weise können Anwender die Kommunikation gestalten und per SSL beziehungsweise TLS absichern.

SSL/TLS-Netzwerkprogrammierung mit Boost.Asio

Das WOPR-Szenario ist gut geeignet, um die Fähigkeiten von Boost.Asio im Bereich der SSL/TLS-Netzwerkprogrammierung zu demonstrieren und auszuloten. Der erste Teil dieser Artikelreihe führt in die Grundlagen und Funktionsweise von Boost.Asio ein. Die folgenden Artikel gehen auf die Implementierung des Servers und des Clients sowie die Praxis der Fehlerbehandlung und Grenzen der Plattformunabhängigkeit ein.

Ursprünglich war Boost dazu gedacht, die neuen Vorschläge, die dem C++-Standardisierungskomitee vorlagen, auszuprobieren. Heute ist die Bibliothekssammlung jedoch weit mehr als eine Spielwiese der Standardisierung. Trotzdem fließt weiterhin vieles von ihr in neue C++-Sprachstandards ein.

2005 erschien Boost.Asio als Teil von Boost 1.35. Dabei handelt es sich um eine plattformübergreifende Bibliothek, die hauptsächlich Funktionen für die Netzwerkprogrammierung mitbringt. Zusätzlich bietet sie Möglichkeiten der Low-Level-I/O-Programmierung, beispielsweise für serielle Schnittstellen und Dateien. Ob Boost.Asio ein Socket, eine Hardware-Schnittstelle oder eine Datei anspricht, bleibt für den Programmierer unerheblich. Er kann die immer gleichen Routinen zum Lesen und Schreiben einsetzen. Die Bibliothek bietet jeweils die Möglichkeit zum synchronen oder asynchronen Zugriff.

Boost.Asio ist eine reine Header-Bibliothek. Sie benötigt also keine zusätzliche Library, gegen die der Objektcode des C++-Programms gelinkt werden müsste. Sobald Entwickler den Header boost/asio.hpp einbinden, steht Boost.Asio im Programm zur Verfügung. Ein weiteres #include <boost/ssl/asio.hpp> und die SSL-Funktionen stehen ebenfalls bereit.

Das ist zwar elegant, aber leider nur die halbe Wahrheit. Boost.Asio hängt von einigen Bibliotheken aus dem Boost-Fundus ab. So benötigt sie in jedem Fall Boost.System, welche die Unterstützung für das jeweilige Betriebssystem beisteuert. Je nachdem, welche Boost.Asio-Features das C++-Programm verwendet, sind noch Boost.Regex für reguläre Ausdrücke, Boost.DateTime für das Verarbeiten und Darstellen von Datums- und Zeitangaben sowie OpenSSL für die TLS/SSL-Unterstützung nötig. Ganz ohne zur Link-Zeit einzubindende Bibliotheken geht es dann eben doch nicht.

Eine Header-Only Library legt die berechtigte Vermutung nahe, dass über die Header viel Code in die eigenen C++-Quelltexte hineingeschoben wird. Das kann das Kompilieren deutlich in die Länge ziehen. Gerade während der Entwicklungsphase größerer Projekte kann sich das in unangenehm langen Turnaround-Zeiten äußern. Vorkompilierte Header, wie sie einige integrierte Entwicklungsumgebungen anbieten, schaffen hier Abhilfe. Allerdings hält Boost.Asio einen eigenen umgebungsunabhängigen Mechanismus bereit.

Das Rezept ist einfach: Der Entwickler fügt ins Projekt eine beliebige neue C++-Quelltextdatei -- beispielsweise PreCompBoostAsio.cpp -- mit folgender Code-Zeile ein:

#include <boost/asio/impl/src.hpp>

Die Verwendung von SSL erfordert zusätzlich folgende Zeile:

#include <boost/asio/ssl/impl/src.hpp>

Alle anderen C++-Quelltexte benötigen nun das gesetzte Makro BOOST_ASIO_SEPARATE_COMPILATION. Ein einfaches #define reicht aus. Alternativ erledigt das auch ein Compiler-Kommandozeilenschalter, in der Unix-Welt meist -D und /D für Microsofts CL.

Jetzt erfolgt das Kompilieren der Boost.Asio-Anteile ausschließlich und einmalig in PreCompBoostAsio.cpp. Das Kompilieren der anderen (eigenen) C++-Module erfolgt nun deutlich schneller. Entwickler dürfen schließlich nicht das Linken des Objektcodes von PreCompBoostAsio.cpp vergessen.

Anzeige