Einführung: Warum einen HTTP-Client in C++ schreiben?
In der modernen Entwicklung ist die Interaktion mit entfernten Servern eine der Kernaufgaben. Ob es darum geht, Daten von einer REST-API abzurufen, ein Formular an einen Server zu senden oder eine Datei hochzuladen – überall wird das HTTP-Protokoll verwendet. Obwohl Python und JavaScript einfache integrierte Lösungen bieten, bleibt C++ für das Schreiben von leistungsstarken HTTP-Clients gefragt. Dies ist notwendig für eingebettete Systeme, Spiele-Engines, stark ausgelastete Backends oder einfach zum Erlernen der Low-Level-Mechanismen von Netzwerken.
In diesem Artikel werden wir zwei beliebte Ansätze zur Implementierung eines HTTP-Clients in C++ behandeln: die Verwendung der Bibliothek libcurl (cURL) und den moderneren asynchronen Ansatz mit Boost.Beast. Sie erfahren, wie Sie GET- und POST-Anfragen korrekt erstellen, Antworten verarbeiten und typische Fehler vermeiden.
1. Der klassische Ansatz: HTTP-Client in C++ mit libcurl
Die Bibliothek libcurl ist ein bewährtes Werkzeug zur Datenübertragung über verschiedene Protokolle. Sie unterstützt HTTP/1.1, HTTP/2, HTTPS, Authentifizierung, Cookies und vieles mehr. Für C++ gibt es den praktischen Wrapper curl/curl.h, der eine einfache Integration von cURL in Ihr Projekt ermöglicht.
Installation von libcurl
In den meisten Linux-Distributionen ist cURL bereits installiert. Für die Entwicklung wird das Entwicklerpaket benötigt:
sudo apt-get install libcurl4-openssl-dev # Ubuntu/Debianbrew install curl # macOSBeispiel: GET-Anfrage
Schreiben wir einen einfachen HTTP-Client in C++, der Daten von einer öffentlichen API (z.B. JSONPlaceholder) abruft.
#include <iostream>#include <string>#include <curl/curl.h>
// Callback zum Schreiben von Daten in std::stringstatic size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) { ((std::string*)userp)->append((char*)contents, size * nmemb); return size * nmemb;}
int main() { CURL *curl; CURLcode res; std::string readBuffer;
curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init();
if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts/1"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); // Anfrage ausführen res = curl_easy_perform(curl); if(res != CURLE_OK) { std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl; } else { std::cout << "Serverantwort:" << readBuffer << std::endl; } curl_easy_cleanup(curl); } curl_global_cleanup(); return 0;}Beispiel: POST-Anfrage mit JSON
Jetzt senden wir Daten an den Server. Dazu müssen der Inhaltstyp und der Anfragetext angegeben werden.
#include <iostream>#include <string>#include <curl/curl.h>
int main() { CURL *curl; CURLcode res; std::string response; // JSON-Daten zum Senden std::string jsonData = R"({"title": "foo", "body": "bar", "userId": 1})"; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts"); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonData.c_str()); // Header setzen struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); // Callback zum Schreiben der Antwort curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, [](void *contents, size_t size, size_t nmemb, void *userp) -> siz