Kapitel 11
Alle Codedateien dieses Kapitels herunterladen
11_1_1_Netzwerk.cpp
#include <httplib.h>
#include <iostream>
int main()
{
httplib::Client client("http://example.com");
httplib::Result result = client.Get("/");
if (result != nullptr)
{
// Server wurde erreicht
std::cout << result->status << std::endl;
std::cout << result->reason << std::endl;
}
else
{
// Server nicht erreicht
std::cerr << "Verbindungsfehler" << std::endl;
}
return 0;
}
11_1_2_NetzwerkRedirect.cpp
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include <httplib.h>
#include <iostream>
int main()
{
httplib::Client client("http://de.wikipedia.org");
client.set_follow_location(true);
httplib::Result result = client.Get("/");
if (result != nullptr)
{
// Server wurde erreicht
std::cout << result->status << std::endl;
std::cout << result->reason << std::endl;
std::cout << result->location << std::endl;
}
else
{
// Server nicht erreicht
std::cerr << "Verbindungsfehler" << std::endl;
}
return 0;
}
11_2_1_NetzwerkAntworten.cpp
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include <httplib.h>
#include <string>
#include <iostream>
int main()
{
// Mit dem deutschen Wikipedia-Server reden
httplib::Client client("https://de.wikipedia.org");
client.set_follow_location(true);
// API-Optionen wählen, die einen kurzen Absatz liefern
const std::string wikiApi = "/w/api.php?action=query&redirects=1"
"&format=json&utf8=1&prop=extracts&explaintext=1&exsentences=2"
"&titles=";
// Das gewünschte Schlüsselwort anhängen
std::string query = wikiApi + "C++";
// Get-Anfrage abschicken. Die Methode verlangt leider
// einen C-String, daher die Umwandlung mittels c_str()
httplib::Result result = client.Get(query.c_str());
if (result != nullptr)
{
// Server wurde erreicht
if (result->status / 100 != 2)
{
std::cerr << "HTTP status: " << result->status
<< " - " << result->reason << std::endl;
return 1;
}
std::cout << result->body << std::endl;
}
else
{
// Server nicht erreicht
std::cerr << "Verbindungsfehler" << std::endl;
}
return 0;
}
11_2_2_NetzwerkAntwortenParsing.cpp
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include <httplib.h>
#include <string>
#include <iostream>
std::string stupidParser(const std::string& message,
const std::string& key)
{
// Der Schlüssel muss mit Anführungszeichen umgeben sein
const std::string techKey = "\"" + key + "\":";
size_t pos = message.find(techKey);
if (pos == std::string::npos)
{
// Nicht gefunden
return "";
}
// Das erste, öffnende Anführungszeichen nach dem Ende
// des Schlüsselworts
size_t first = message.find('\"', pos + techKey.size());
if (first == std::string::npos)
{
std::cerr << "Ung\201ltiges JSON: " << message << std::endl;
return "";
}
// Das zweite Anführungszeichen ist schon schwieriger,
// denn es dürfte auch innerhalb des Textes auftauchen
// und nicht nur am Ende. Da es in diesem Falle aber mit
// einem Backslash codiert sein müsste, suchen Sie dann
// weiter, wenn ein Backslash davor steht
size_t second = message.find('\"', first + 1);
while (second != std::string::npos
&& message.at(second - 1) == '\\')
{
// Ab dem gefundenen codierten Zeichen weitersuchen
second = message.find('\"', second + 1);
}
if (second == std::string::npos)
{
std::cerr << "Ung\201ltiges JSON: " << message << std::endl;
return "";
}
// Eins addieren, um das Anführungszeichen auszuschließen
first++;
// first und second sind Indizes. Daher erhalten Sie die
// Länge des gewünschten Substrings, indem Sie sie
// voneinander abziehen.
return message.substr(first, second - first);
}
int main()
{
// Mit dem deutschen Wikipedia-Server reden
httplib::Client client("https://de.wikipedia.org");
client.set_follow_location(true);
// API-Optionen wählen, die einen kurzen Absatz liefern
const std::string wikiApi = "/w/api.php?action=query&redirects=1"
"&format=json&utf8=1&prop=extracts&explaintext=1&exsentences=2"
"&titles=";
// Das gewünschte Schlüsselwort anhängen
std::string query = wikiApi + "C++";
// Get-Anfrage abschicken. Die Methode verlangt leider
// einen C-String, daher die Umwandlung mittels c_str()
httplib::Result result = client.Get(query.c_str());
if (result != nullptr)
{
// Server wurde erreicht
if (result->status / 100 == 2)
{
std::cout << stupidParser(result->body, "extract")
<< std::endl;
}
else
{
std::cerr << "HTTP status: " << result->status
<< " - " << result->reason << std::endl;
}
}
else
{
// Server nicht erreicht
std::cerr << "Verbindungsfehler" << std::endl;
}
return 0;
}
11_3_JsonAntwort.cpp
#include <json/json.h>
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include <httplib.h>
#include <string>
#include <iostream>
int main()
{
// Mit dem deutschen Wikipedia-Server reden
httplib::Client client("https://de.wikipedia.org");
client.set_follow_location(true);
// API-Optionen wählen, die einen kurzen Absatz liefern
const std::string wikiApi = "/w/api.php?action=query&redirects=1"
"&format=json&utf8=1&prop=extracts&explaintext=1&exsentences=2"
"&titles=";
// Das gewünschte Schlüsselwort anhängen
std::string query = wikiApi + "C++";
// Get-Anfrage abschicken. Die Methode verlangt leider
// einen C-String, daher die Umwandlung mittels c_str()
httplib::Result result = client.Get(query.c_str());
if (result != nullptr)
{
// Server wurde erreicht
if (result->status / 100 == 2)
{
Json::Value answer;
// Der Reader liest den String in die Variable ein
Json::Reader().parse(result->body, answer);
// Zugriff auf Eigenschaften mit eckigen Klammern.
// Bei Objekten innerhalb von Objekten (siehe #1)
// können Sie die eckigen Klammern nacheinander
// schreiben:
Json::Value pages = answer["query"]["pages"];
// Die nun folgende Eigenschaft hat keinen fest-
// stehenden Schlüssel, sondern entspricht der
// Page-ID (siehe #2). Daher müssen wir zuerst den
// Schlüssel selbst abfragen.
std::string pageName = pages.getMemberNames().at(0);
// Der abgefragte Schlüssel kann nun in die eckigen
// Klammern geschrieben werden. Danach folgt ein
// weiteres Klammerpaar, in dem die Ziel-Eigenschaft,
// der "extract", steht. Siehe #3
Json::Value page = pages[pageName]["extract"];
std::string extract = page.asString();
std::cout << extract << std::endl;
}
else
{
std::cerr << "HTTP status: " << result->status
<< " - " << result->reason << std::endl;
}
}
else
{
// Server nicht erreicht
std::cerr << "Verbindungsfehler" << std::endl;
}
return 0;
}
11_4_1_NetzwerkGUI.cpp
#include <json/json.h>
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include <httplib.h>
#include <string>
#include <iostream>
#include <nana/gui.hpp>
#include <nana/gui/widgets/label.hpp>
#include <nana/gui/widgets/textbox.hpp>
#include <nana/gui/widgets/button.hpp>
int main()
{
// Ein Nana-Formular als Basis des Fensters anlegen
nana::form window;
window.caption("Wikipedia-Suche");
// Die GUI-Elemente anlegen
nana::label txt(window);
txt.text_align(nana::align::center, nana::align_v::center);
nana::textbox input(window);
input.multi_lines(false);
nana::button button(window, "Senden");
// Das Label dem Layout hinzufügen
window.div("vertical"
"<txt margin=10>"
"<height=30 <input><button fit>>");
window["txt"] << txt;
window["input"] << input;
window["button"] << button;
window.collocate();
// Mit dem deutschen Wikipedia-Server reden
httplib::Client client("https://de.wikipedia.org");
client.set_follow_location(true);
// API-Optionen wählen, die einen kurzen Absatz liefern
const std::string wikiApi = "/w/api.php?action=query&redirects=1"
"&format=json&utf8=1&prop=extracts&explaintext=1&exsentences=2"
"&titles=";
button.events().click([&]() {
if (input.text().empty())
{
// Kein Suchtext vorhanden. Nichts machen
return;
}
// Das gewünschte Schlüsselwort anhängen
std::string query = wikiApi + input.text();
// Get-Anfrage abschicken. Die Methode verlangt leider
// einen C-String, daher die Umwandlung mittels c_str()
httplib::Result result = client.Get(query.c_str());
if (result != nullptr)
{
// Server wurde erreicht
if (result->status / 100 == 2)
{
Json::Value answer;
// Der Reader liest den String in die Variable ein
Json::Reader().parse(result->body, answer);
// Aufruf der gewünschten Eigenschaften
Json::Value pages = answer["query"]["pages"];
std::string pageName = pages.getMemberNames().at(0);
Json::Value page = pages[pageName];
std::string extract = page["extract"].asString();
// Extract in das Textlabel geben
txt.caption(extract);
}
else
{
std::cerr << "HTTP status: " << result->status
<< " - " << result->reason << std::endl;
}
}
else
{
// Server nicht erreicht
std::cerr << "Verbindungsfehler" << std::endl;
}
});
// Fenster anzeigen und Nana starten
window.show();
nana::exec();
return 0;
}
11_4_2_NetzwerkGUIBild.cpp
#include <json/json.h>
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include <httplib.h>
#include <string>
#include <iostream>
#include <nana/gui.hpp>
#include <nana/gui/widgets/label.hpp>
#include <nana/gui/widgets/textbox.hpp>
#include <nana/gui/widgets/button.hpp>
#include <nana/paint/image.hpp>
#include <nana/gui/widgets/picture.hpp>
std::pair<std::string, std::string> splitUrl(
const std::string& url)
{
size_t pos = url.find("//");
if (pos == std::string::npos)
{
return { url, "" };
}
// Finde den ersten Slash nach dem Doppelslash
pos = url.find('/', pos + 2);
if (pos == std::string::npos)
{
return { url, "" };
}
return { url.substr(0, pos), url.substr(pos) };
}
nana::paint::image loadImage(const std::string& url)
{
if (url.size() == 0)
{
// Nichts zum Herunterladen. Leeres Bild zurückgeben
return nana::paint::image();
}
// Die URL muss in den Server und den Pfad
// aufgetrennt werden.
const auto urlParts = splitUrl(url);
const std::string server = urlParts.first;
const std::string path = urlParts.second;
httplib::Client client(server.c_str());
client.set_follow_location(true);
httplib::Result result = client.Get(path.c_str());
if (!result || result->status / 100 != 2)
{
// Abfrage fehlgeschlagen. Ein leeres Bild zurückgeben
std::cerr << "HTTP status: " << result->status
<< " - " << result->reason << std::endl;
return nana::paint::image();
}
// Das Bild aus der Serverantwort auslesen
nana::paint::image image;
image.open(result->body.c_str(), result->body.size());
return image;
}
int main()
{
// Ein Nana-Formular als Basis des Fensters anlegen
nana::form window;
window.caption("Wikipedia-Suche");
// Die GUI-Elemente anlegen
nana::label txt(window);
txt.text_align(nana::align::center, nana::align_v::center);
nana::textbox input(window);
input.multi_lines(false);
nana::button button(window, "Senden");
nana::picture picture(window);
picture.align(nana::align::center, nana::align_v::center);
// Das Label dem Layout hinzufügen
window.div("vertical"
"<picture height=50>"
"<txt margin=10>"
"<height=30 <input><button fit>>");
window["picture"] << picture;
window["txt"] << txt;
window["input"] << input;
window["button"] << button;
window.collocate();
// Mit dem deutschen Wikipedia-Server reden
httplib::Client client("https://de.wikipedia.org");
client.set_follow_location(true);
// API-Optionen wählen, die einen kurzen Absatz sowie
// "pageimages" liefern.
const std::string wikiApi = "/w/api.php?action=query&redirects=1"
"&format=json&utf8=1&prop=extracts|pageimages&explaintext=1"
"&exsentences=2&pilicense=any&titles=";
button.events().click([&]() {
if (input.text().empty())
{
// Kein Suchtext vorhanden. Nichts machen
return;
}
// Das gewünschte Schlüsselwort anhängen
std::string query = wikiApi + input.text();
// Get-Anfrage abschicken. Die Methode verlangt leider
// einen C-String, daher die Umwandlung mittels c_str()
httplib::Result result = client.Get(query.c_str());
if (result != nullptr)
{
// Server wurde erreicht
if (result->status / 100 == 2)
{
Json::Value answer;
// Der Reader liest den String in die Variable ein
Json::Reader().parse(result->body, answer);
// Aufruf der gewünschten Eigenschaften
Json::Value pages = answer["query"]["pages"];
std::string pageName = pages.getMemberNames().at(0);
Json::Value page = pages[pageName];
std::string extract = page["extract"].asString();
// Extract in das Textlabel geben
txt.caption(extract);
// Artikelbild laden und anzeigen
Json::Value thumbnail = page["thumbnail"]["source"];
std::string thumbnailUrl = thumbnail.asString();
picture.load(loadImage(thumbnailUrl));
}
else
{
std::cerr << "HTTP status: " << result->status
<< " - " << result->reason << std::endl;
}
}
else
{
// Server nicht erreicht
std::cerr << "Verbindungsfehler" << std::endl;
}
});
// Fenster anzeigen und Nana starten
window.show();
nana::exec();
return 0;
}
11_5_1_Serialisierung.cpp
#include <json/json.h>
#include <iostream>
#include <string>
struct Question
{
std::string question;
std::string answer;
int category = 0;
void read(const std::string& str)
{
// Deserialisierung: Auslesen aus einem String
Json::Value jsonObj;
Json::Reader().parse(str, jsonObj);
// Abruf der gewünschten Eigenschaften
question = jsonObj["question"].asString();
answer = jsonObj["answer"].asString();
category = jsonObj["category"].asInt();
}
std::string write() const
{
// Serialisierung: Abspeichern in einem String
Json::StreamWriterBuilder factory;
Json::Value jsonObj;
jsonObj["question"] = question;
jsonObj["answer"] = answer;
jsonObj["category"] = category;
return Json::writeString(factory, jsonObj);
}
};
int main()
{
Question q1;
q1.question = "Was macht es?";
q1.answer = "Es leuchtet blau";
q1.category = 2;
std::cout << q1.write() << std::endl;
Question q2;
q2.read(q1.write());
std::cout << q2.write() << std::endl;
return 0;
}
11_5_2_SerialisierungAbstract.cpp
#include <json/json.h>
#include <iostream>
#include <string>
struct SerializableType
{
virtual std::string write() const = 0;
virtual void read(const std::string& str) = 0;
};
struct Question : public SerializableType
{
std::string question;
std::string answer;
int category = 0;
void read(const std::string& str) override
{
// Deserialisierung: Auslesen aus einem String
Json::Value jsonObj;
Json::Reader().parse(str, jsonObj);
// Abruf der gewünschten Eigenschaften
question = jsonObj["question"].asString();
answer = jsonObj["answer"].asString();
category = jsonObj["category"].asInt();
}
std::string write() const override
{
// Serialisierung: Abspeichern in einem String
Json::StreamWriterBuilder factory;
Json::Value jsonObj;
jsonObj["question"] = question;
jsonObj["answer"] = answer;
jsonObj["category"] = category;
return Json::writeString(factory, jsonObj);
}
};
struct User : public SerializableType
{
std::string name;
int id = 0;
void read(const std::string& str) override
{
Json::Value jsonObj;
Json::Reader().parse(str, jsonObj);
name = jsonObj["name"].asString();
id = jsonObj["id"].asInt();
}
std::string write() const override
{
Json::StreamWriterBuilder factory;
Json::Value jsonObj;
jsonObj["name"] = name;
jsonObj["id"] = id;
return Json::writeString(factory, jsonObj);
}
};
void printOnConsole(const SerializableType& type)
{
std::cout << type.write() << std::endl;
}
int main()
{
Question q1;
q1.question = "Was macht es?";
q1.answer = "Es leuchtet blau";
q1.category = 2;
std::cout << q1.write() << std::endl;
Question q2;
q2.read(q1.write());
std::cout << q2.write() << std::endl;
User user;
user.name = "Manfred";
user.id = 17;
std::cout << user.write() << std::endl;
printOnConsole(q1);
printOnConsole(q2);
printOnConsole(user);
return 0;
}