373 Stimmen

Wie macht man eine HTTP-Anfrage mit C++?

Gibt es eine Möglichkeit, mit C++ leicht einen HTTP-Request zu erstellen? Speziell möchte ich den Inhalt einer Seite (einer API) herunterladen und den Inhalt überprüfen, um zu sehen, ob er eine 1 oder eine 0 enthält. Ist es auch möglich, den Inhalt in einen String herunterzuladen?

2 Stimmen

Nein, derzeit gibt es keine integrierte Unterstützung entweder über die Sprache oder die Standardbibliothek für Netzwerke. Es gibt jedoch einen Networking TS N4370. Ich habe auch für diese Frage gestimmt, da sie Bibliotheksempfehlungen anzieht.

0 Stimmen

Wie wäre es mit BoostBeast?

3 Stimmen

@user3920237 Glücklicherweise denken die meisten Menschen nicht destruktiv, um die nützliche Frage zu VTC. Diese sind für den Gebrauch der Menschen gemacht, sei es Bibliothek.

20voto

Mark Lakata Punkte 18998

Hier ist meine minimale Wrapper um cURL, um einfach eine Webseite als Zeichenfolge abzurufen. Dies ist nützlich, zum Beispiel für Unittests. Es handelt sich im Grunde um einen RAII-Wrapper um den C-Code.

Installieren Sie "libcurl" auf Ihrem Gerät yum install libcurl libcurl-devel oder Ähnliches.

Beispiel für die Verwendung:

CURLplusplus client;
string x = client.Get("http://google.com");
string y = client.Get("http://yahoo.com");

Implementierung der Klasse:

#include 

class CURLplusplus
{
private:
    CURL* curl;
    stringstream ss;
    long http_code;
public:
    CURLplusplus()
            : curl(curl_easy_init())
    , http_code(0)
    {

    }
    ~CURLplusplus()
    {
        if (curl) curl_easy_cleanup(curl);
    }
    std::string Get(const std::string& url)
    {
        CURLcode res;
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);

        ss.str("");
        http_code = 0;
        res = curl_easy_perform(curl);
        if (res != CURLE_OK)
        {
            throw std::runtime_error(curl_easy_strerror(res));
        }
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        return ss.str();
    }
    long GetHttpCode()
    {
        return http_code;
    }
private:
    static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp)
    {
        return static_cast(userp)->Write(buffer,size,nmemb);
    }
    size_t Write(void *buffer, size_t size, size_t nmemb)
    {
        ss.write((const char*)buffer,size*nmemb);
        return size*nmemb;
    }
};

19voto

Marcelo Santos Punkte 1831

Da du eine C++-Lösung möchtest, könntest du Qt verwenden. Es hat eine QHttp-Klasse, die du verwenden kannst.

Du kannst die Dokumentation überprüfen:

http->setHost("qt.nokia.com");
http->get(QUrl::toPercentEncoding("/index.html"));

Qt bietet auch noch viel mehr, das du in einer gewöhnlichen C++-Anwendung nutzen könntest.

7 Stimmen

Ich denke, dass QHttp in Qt 4.6 und späteren Versionen durch QNetworkAccessManager und verwandte Klassen ersetzt wurde.

4 Stimmen

QNetworkAccessManager wurde seit Qt 4.4 dokumentiert; und in Qt 4.8 heißt es: QHttp - Diese Klasse ist veraltet. Sie wird bereitgestellt, um alten Quellcode am Laufen zu halten. Wir raten dringend davon ab, sie in neuem Code zu verwenden. Ich denke also, dass sie immer noch verfügbar ist, wenn man die veralteten Warnungen ignoriert.

17voto

copperoxide Punkte 189

Sie möchten vielleicht C++ REST SDK (Codename "Casablanca") überprüfen. http://msdn.microsoft.com/en-us/library/jj950081.aspx

Mit dem C++ REST SDK können Sie einfacher Verbindungen zu HTTP-Servern von Ihrer C++-Anwendung aus herstellen.

Verwendungsbeispiel:

#include 
#include 

using namespace web::http;                  // Gemeinsame HTTP-Funktionalitäten
using namespace web::http::client;          // Funktionen des HTTP-Clients

int main(int argc, char** argv) {
    http_client client("http://httpbin.org/");

    http_response response;
    // normale `get` Anfrage
    response = client.request(methods::GET, "/get").get();
    std::cout << response.extract_string().get() << "\n";

    // Arbeiten mit JSON
    response = client.request(methods::GET, "/get").get();
    std::cout << "URL: " << response.extract_json().get()[U("url")] << "\n";
}

Das C++ REST SDK ist ein Microsoft-Projekt für die clientseitig-serverseitige Kommunikation in nativem Code unter Verwendung eines modernen asynchronen C++-API-Designs.

0 Stimmen

Das Projekt scheint jetzt nicht mehr gewartet zu werden, bitte beachten Sie dies bei der Verwendung in der Produktion. Die Qualität ist nicht hoch genug, um den Standards in Produktionsumgebungen zu entsprechen.

15voto

FreeMemory Punkte 8382

libCURL ist eine ziemlich gute Option für dich. Abhängig von dem, was du tun musst, sollte das Tutorial dir sagen, was du speziell für den einfachen Handgriff brauchst. Aber grundsätzlich könntest du dies einfach tun, um die Quelle einer Seite zu sehen:

CURL* c;
c = curl_easy_init();
curl_easy_setopt( c, CURL_URL, "www.google.com" );
curl_easy_perform( c );
curl_easy_cleanup( c );

Ich glaube, dies wird dazu führen, dass das Ergebnis auf der Standardausgabe gedruckt wird. Wenn du es stattdessen verarbeiten möchtest -- was ich annehme, dass du es möchtest -- musst du die CURL_WRITEFUNCTION setzen. All das wird im oben verlinkten curl Tutorial behandelt.

0 Stimmen

Libcurl ist C, nicht C++

14voto

Vinz Punkte 2749

Mit dieser Antwort beziehe ich mich auf die Antwort von Software_Developer. Beim Neuaufbau des Codes habe ich festgestellt, dass einige Teile veraltet sind (gethostbyname()) oder keine Fehlerbehandlung bieten (Erstellen von Sockets, Senden von Daten) für einen Vorgang.

Der folgende Windows-Code wurde mit Visual Studio 2013 und Windows 8.1 64-Bit sowie Windows 7 64-Bit getestet. Er zielt auf eine IPv4 TCP-Verbindung zum Webserver von www.google.com ab.

#include 
#include 
#include 
#include 
#pragma comment(lib,"ws2_32.lib")
using namespace std;
    int main (){
    // Initialisierung der Abhängigkeiten zum Windows Socket.
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
        cout << "WSAStartup fehlgeschlagen.\n";
        system("pause");
        return -1;
    }

    // Zuerst bereiten wir einige "Hints" für die Funktion "getaddrinfo" vor
    // damit sie wissen, dass wir eine IPv4 TCP-Verbindung suchen.
    struct addrinfo hints;
    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;          // Wir zielen auf IPv4
    hints.ai_protocol = IPPROTO_TCP;    // Wir zielen auf TCP
    hints.ai_socktype = SOCK_STREAM;    // Wir zielen auf TCP, daher SOCK_STREAM

    // Erlangen der IPv4-Adresse eines Hosts unter Verwendung der neueren
    // Funktion "getaddrinfo", welche "gethostbyname" veraltet ist.
    // Sie wird nach IPv4-Adressen unter Verwendung des TCP-Protokolls suchen.
    struct addrinfo* targetAdressInfo = NULL;
    DWORD getAddrRes = getaddrinfo("www.google.com", NULL, &hints, &targetAdressInfo);
    if (getAddrRes != 0 || targetAdressInfo == NULL)
    {
        cout << "Der Hostname konnte nicht aufgelöst werden" << endl;
        system("pause");
        WSACleanup();
        return -1;
    }

    // Erstellung der Socket Address Informationen unter Verwendung von IPv4
    // Wir müssen uns nicht um sin_zero kümmern, es wird nur verwendet, um die Länge von SOCKADDR_IN auf die Größe von SOCKADDR zu erweitern
    SOCKADDR_IN sockAddr;
    sockAddr.sin_addr = ((struct sockaddr_in*) targetAdressInfo->ai_addr)->sin_addr;    // Die IPv4-Adresse aus dem Adressauflösungsergebnis
    sockAddr.sin_family = AF_INET;  // IPv4
    sockAddr.sin_port = htons(80);  // HTTP-Port: 80

    // Wir müssen die Adressinformationen von getaddrinfo wieder freigeben
    freeaddrinfo(targetAdressInfo);

    // Erstellung eines Sockets für die Kommunikation mit dem Webserver,
    // unter Verwendung von IPv4 und dem TCP-Protokoll
    SOCKET webSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (webSocket == INVALID_SOCKET)
    {
        cout << "Erstellung des Sockets ist fehlgeschlagen" << endl;
        system("pause");
        WSACleanup();
        return -1;
    }

    // Verbindungsherstellung mit dem Websocket
    cout << "Verbinde...\n";
    if(connect(webSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr)) != 0)
    {
        cout << "Verbindung konnte nicht hergestellt werden";
        system("pause");
        closesocket(webSocket);
        WSACleanup();
        return -1;
    }
    cout << "Verbunden.\n";

    // Senden einer HTTP-GET-Anforderung an den Webserver
    const char* httpRequest = "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n";
    int gesendeteBytes = send(webSocket, httpRequest, strlen(httpRequest),0);
    if (gesendeteBytes < strlen(httpRequest) || gesendeteBytes == SOCKET_ERROR)
    {
        cout << "Anfrage konnte nicht an den Server gesendet werden" << endl;
        system("pause");
        closesocket(webSocket);
        WSACleanup();
        return -1;
    }

    // Empfangen und Anzeigen einer Antwort des Webservers
    char buffer[10000];
    ZeroMemory(buffer, sizeof(buffer));
    int datenLänge;
    while ((datenLänge = recv(webSocket, buffer, sizeof(buffer), 0) > 0))
    {
        int i = 0;
        while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
            cout << buffer[i];
            i += 1;
        }
    }

    // Bereinigung der Windows Socket-Abhängigkeiten
    closesocket(webSocket);
    WSACleanup();

    system("pause");
    return 0;
}

Referenzen:

Veraltetes gethostbyname

Rückgabewert von socket()

Rückgabewert von send()

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X