Wie machen Sie eine HTTP-Anfrage mit C++?

Lesezeit: 12 Minuten

Wie machen Sie eine HTTP Anfrage mit C
Sam152

Gibt es eine Möglichkeit, mit C++ einfach eine HTTP-Anfrage zu stellen? Konkret möchte ich den Inhalt einer Seite (eine API) herunterladen und den Inhalt prüfen, ob er eine 1 oder eine 0 enthält. Ist es auch möglich, den Inhalt in einen String herunterzuladen?

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

    Benutzer3920237

    11. März 2015 um 9:22 Uhr

  • Wie wäre es mit BoostBeast?

    – happy_sisyphos

    27. September 2018 um 2:04 Uhr

  • @ user3920237 Glücklicherweise denken die meisten Leute nicht destruktiv, um VTC die nützliche Frage zu stellen. Diese sind für den Gebrauch der Leute gemacht, lass es eine Bibliothek sein.

    – T. Todua

    17. September 2020 um 18:19 Uhr


Wie machen Sie eine HTTP Anfrage mit C
Neuro

Ich hatte das gleiche Problem. libcurl ist wirklich vollständig. Es gibt einen C++-Wrapper curlpp das könnte Sie interessieren, wenn Sie nach einer C++-Bibliothek fragen. Neon- ist eine weitere interessante C-Bibliothek, die ebenfalls unterstützt WebDAV.

curlpp erscheint natürlich, wenn Sie C++ verwenden. Es gibt viele Beispiele, die in der Quelldistribution bereitgestellt werden. Um den Inhalt einer URL zu erhalten, gehen Sie so vor (aus Beispielen entnommen):

// Edit : rewritten for cURLpp 0.7.3
// Note : namespace changed, was cURLpp in 0.7.2 ...

#include <curlpp/cURLpp.hpp>
#include <curlpp/Options.hpp>

// RAII cleanup

curlpp::Cleanup myCleanup;

// Send request and get a result.
// Here I use a shortcut to get it in a string stream ...

std::ostringstream os;
os << curlpp::options::Url(std::string("http://example.com"));

string asAskedInQuestion = os.str();

Siehe die examples Verzeichnis ein curlpp-Quellverteilunggibt es viele komplexere Fälle, sowie a einfach komplett minimal mit curlpp.

meine 2 cent…

  • Die neueste Version scheint unter Mac kaputt zu sein. Etwas ist mit config.h durcheinander, wenn es als Bibliothek verknüpft wird.

    – Eugen

    8. April 2011 um 0:59 Uhr

  • Nun, ich konnte das oben nicht kompilieren. Allerdings ersetzen os << myRequest.perform(); mit myRequest.setOpt( new curlpp::options::WriteStream( &os ) ); myRequest.perform(); gab Ergebnisse. Achten Sie darauf, nicht zu verwenden http://example.com, wird eine leere Seite zurückgegeben. Verwenden Sie besser zB http://www.wikipedia.org.

    – Zane

    4. November 2012 um 14:22 Uhr


  • Wie baut man curlpp in MSVS? Ich bekomme es nicht zum Laufen 🙁

    – mr5

    15. November 2016 um 6:43 Uhr

  • Ich stimme der letzten Änderung von @ryan-sam nicht zu. Es war eindeutig die Absicht des Autors, “Webdav” und nicht Webentwicklung zu schreiben, da die angegebene Bibliothek explizit für “HTTP- und WebDAV-Operationen” erstellt wurde.

    – Bostrot

    5. Dezember 2018 um 11:20 Uhr

  • @bostrot: Ja, das meinte ich. Ich kehrte zurück und fügte einen Link hinzu, ich glaube, die Leute dachten, ich hätte Webdev geschrieben. Was für eine Schande 🙂

    – Neuro

    5. Dezember 2018 um 13:43 Uhr

1647079811 351 Wie machen Sie eine HTTP Anfrage mit C
Software Designer

Windows-Code:

#include <string.h>
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <vector>
#include <locale>
#include <sstream>
using namespace std;
#pragma comment(lib,"ws2_32.lib")




int main( void ){

WSADATA wsaData;
SOCKET Socket;
SOCKADDR_IN SockAddr;
int lineCount=0;
int rowCount=0;
struct hostent *host;
locale local;
char buffer[10000];
int i = 0 ;
int nDataLength;
string website_HTML;

// website url
string url = "www.google.com";

//HTTP GET
string get_http = "GET / HTTP/1.1\r\nHost: " + url + "\r\nConnection: close\r\n\r\n";


    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0){
        cout << "WSAStartup failed.\n";
        system("pause");
        //return 1;
    }

    Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    host = gethostbyname(url.c_str());

    SockAddr.sin_port=htons(80);
    SockAddr.sin_family=AF_INET;
    SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);

    if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0){
        cout << "Could not connect";
        system("pause");
        //return 1;
    }

    // send GET / HTTP
    send(Socket,get_http.c_str(), strlen(get_http.c_str()),0 );

    // recieve html
    while ((nDataLength = recv(Socket,buffer,10000,0)) > 0){        
        int i = 0;
        while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r'){

            website_HTML+=buffer[i];
            i += 1;
        }               
    }

    closesocket(Socket);
    WSACleanup();

    // Display HTML source 
    cout<<website_HTML;

    // pause
    cout<<"\n\nPress ANY key to close.\n\n";
    cin.ignore(); cin.get(); 


 return 0;
}

Hier ist eine viel bessere Implementierung:

#include <windows.h>
#include <string>
#include <stdio.h>

using std::string;

#pragma comment(lib,"ws2_32.lib")


HINSTANCE hInst;
WSADATA wsaData;
void mParseUrl(char *mUrl, string &serverName, string &filepath, string &filename);
SOCKET connectToServer(char *szServerName, WORD portNum);
int getHeaderLength(char *content);
char *readUrl2(char *szUrl, long &bytesReturnedOut, char **headerOut);


int main()
{
    const int bufLen = 1024;
    char *szUrl = "http://stackoverflow.com";
    long fileSize;
    char *memBuffer, *headerBuffer;
    FILE *fp;

    memBuffer = headerBuffer = NULL;

    if ( WSAStartup(0x101, &wsaData) != 0)
        return -1;


    memBuffer = readUrl2(szUrl, fileSize, &headerBuffer);
    printf("returned from readUrl\n");
    printf("data returned:\n%s", memBuffer);
    if (fileSize != 0)
    {
        printf("Got some data\n");
        fp = fopen("downloaded.file", "wb");
        fwrite(memBuffer, 1, fileSize, fp);
        fclose(fp);
         delete(memBuffer);
        delete(headerBuffer);
    }

    WSACleanup();
    return 0;
}


void mParseUrl(char *mUrl, string &serverName, string &filepath, string &filename)
{
    string::size_type n;
    string url = mUrl;

    if (url.substr(0,7) == "http://")
        url.erase(0,7);

    if (url.substr(0,8) == "https://")
        url.erase(0,8);

    n = url.find("https://stackoverflow.com/");
    if (n != string::npos)
    {
        serverName = url.substr(0,n);
        filepath = url.substr(n);
        n = filepath.rfind("https://stackoverflow.com/");
        filename = filepath.substr(n+1);
    }

    else
    {
        serverName = url;
        filepath = "https://stackoverflow.com/";
        filename = "";
    }
}

SOCKET connectToServer(char *szServerName, WORD portNum)
{
    struct hostent *hp;
    unsigned int addr;
    struct sockaddr_in server;
    SOCKET conn;

    conn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (conn == INVALID_SOCKET)
        return NULL;

    if(inet_addr(szServerName)==INADDR_NONE)
    {
        hp=gethostbyname(szServerName);
    }
    else
    {
        addr=inet_addr(szServerName);
        hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
    }

    if(hp==NULL)
    {
        closesocket(conn);
        return NULL;
    }

    server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
    server.sin_family=AF_INET;
    server.sin_port=htons(portNum);
    if(connect(conn,(struct sockaddr*)&server,sizeof(server)))
    {
        closesocket(conn);
        return NULL;
    }
    return conn;
}

int getHeaderLength(char *content)
{
    const char *srchStr1 = "\r\n\r\n", *srchStr2 = "\n\r\n\r";
    char *findPos;
    int ofset = -1;

    findPos = strstr(content, srchStr1);
    if (findPos != NULL)
    {
        ofset = findPos - content;
        ofset += strlen(srchStr1);
    }

    else
    {
        findPos = strstr(content, srchStr2);
        if (findPos != NULL)
        {
            ofset = findPos - content;
            ofset += strlen(srchStr2);
        }
    }
    return ofset;
}

char *readUrl2(char *szUrl, long &bytesReturnedOut, char **headerOut)
{
    const int bufSize = 512;
    char readBuffer[bufSize], sendBuffer[bufSize], tmpBuffer[bufSize];
    char *tmpResult=NULL, *result;
    SOCKET conn;
    string server, filepath, filename;
    long totalBytesRead, thisReadSize, headerLen;

    mParseUrl(szUrl, server, filepath, filename);

    ///////////// step 1, connect //////////////////////
    conn = connectToServer((char*)server.c_str(), 80);

    ///////////// step 2, send GET request /////////////
    sprintf(tmpBuffer, "GET %s HTTP/1.0", filepath.c_str());
    strcpy(sendBuffer, tmpBuffer);
    strcat(sendBuffer, "\r\n");
    sprintf(tmpBuffer, "Host: %s", server.c_str());
    strcat(sendBuffer, tmpBuffer);
    strcat(sendBuffer, "\r\n");
    strcat(sendBuffer, "\r\n");
    send(conn, sendBuffer, strlen(sendBuffer), 0);

//    SetWindowText(edit3Hwnd, sendBuffer);
    printf("Buffer being sent:\n%s", sendBuffer);

    ///////////// step 3 - get received bytes ////////////////
    // Receive until the peer closes the connection
    totalBytesRead = 0;
    while(1)
    {
        memset(readBuffer, 0, bufSize);
        thisReadSize = recv (conn, readBuffer, bufSize, 0);

        if ( thisReadSize <= 0 )
            break;

        tmpResult = (char*)realloc(tmpResult, thisReadSize+totalBytesRead);

        memcpy(tmpResult+totalBytesRead, readBuffer, thisReadSize);
        totalBytesRead += thisReadSize;
    }

    headerLen = getHeaderLength(tmpResult);
    long contenLen = totalBytesRead-headerLen;
    result = new char[contenLen+1];
    memcpy(result, tmpResult+headerLen, contenLen);
    result[contenLen] = 0x0;
    char *myTmp;

    myTmp = new char[headerLen+1];
    strncpy(myTmp, tmpResult, headerLen);
    myTmp[headerLen] = NULL;
    delete(tmpResult);
    *headerOut = myTmp;

    bytesReturnedOut = contenLen;
    closesocket(conn);
    return(result);
}

  • Ich konnte curlpp nicht zum Laufen bringen, also habe ich Ihren Code verwendet, danke

    – Scherif Marzouk

    25. November 2012 um 11:04 Uhr

  • Versuchte diesen Code auf einem Windows Vista, das mit Dev-C++ Version 4.9.9.2 kompiliert wurde. Ich habe mir beim Verlinken ein paar Fehler gemacht: [Linker error] undefinierter Verweis auf `WSAStartup@8′

    – Expanding-Dev

    2. April 2014 um 20:15 Uhr

  • @Expanding-Dev Nur MSVC (Visual Studio) versteht “Pragma-Kommentar”. Wenn Sie etwas anderes verwenden, müssen Sie “ws2_32.lib” manuell verknüpfen (wie jede andere Bibliothek).

    – Navin

    15. Mai 2014 um 18:37 Uhr

  • Was soll hier (mittels recv) empfangen werden? Ich bekomme eine Menge Kauderwelsch als Ausgabe. Warum haben Sie das, was Sie getan haben, in den Sendepuffer geschrieben (z GET / HTTP/1.1.1/... etc)? Wie finde ich heraus, wie ich das, was ich sende, formatieren muss?

    – LazerSharks

    8. September 2014 um 0:27 Uhr


Wie machen Sie eine HTTP Anfrage mit C
Homer6

Aktualisierung 2020: Ich habe eine neue Antwort, die diese jetzt 8 Jahre alte ersetzt: https://stackoverflow.com/a/61177330/278976

Unter Linux habe ich cpp-netlib, libcurl, curlpp, urdl, boost::asio ausprobiert und Qt in Betracht gezogen (aber aufgrund der Lizenz abgelehnt). Alle diese waren entweder für diese Verwendung unvollständig, hatten schlampige Schnittstellen, hatten eine schlechte Dokumentation, wurden nicht gepflegt oder unterstützten kein https.

Dann habe ich auf Vorschlag von https://stackoverflow.com/a/1012577/278976 POCO ausprobiert. Wow, ich wünschte, ich hätte das schon vor Jahren gesehen. Hier ist ein Beispiel für eine HTTP GET-Anforderung mit POCO:

https://stackoverflow.com/a/26026828/2817595

POCO ist kostenlos, Open Source (Boost-Lizenz). Und nein, ich habe keine Zugehörigkeit zum Unternehmen; Ich mag einfach ihre Schnittstellen. Tolle Arbeit Jungs (und Mädels).

https://pocoproject.org/download.html

Hoffe, das hilft jemandem … Ich habe drei Tage gebraucht, um alle diese Bibliotheken auszuprobieren.

  • Hier ist ein zusätzliches Beispiel: github.com/pocoproject/poco/blob/develop/Net/samples/httpget/…

    – Homer6

    10. Januar 2014 um 21:32 Uhr

  • Ich habe gerade Poco auf Ihren Vorschlag hin heruntergeladen. Ich würde etwas Leichtes bevorzugen, das auf STL aufbaut und es verstärkt, anstatt viel davon neu zu schreiben. Außerdem bin ich kein Fan von CppUnit und insbesondere hasse ich Tests, die mit dem Build laufen, und erwarte nicht, dass ich ihre Bibliothek testen muss, während ich sie baue.

    – Goldesel

    25. Februar 2014 um 21:30 Uhr


  • Es ist ein bisschen groß. Sie können jedoch das Erstellen der Tests und Beispiele (oder gemeinsam genutzten Bibliotheken) mit configure deaktivieren (dh –no-tests oder –no-samples oder –no-sharedlibs). Sehen github.com/pocoproject/poco/blob/develop/configure

    – Homer6

    25. Februar 2014 um 22:34 Uhr


  • Danke für das. Ich will es trotzdem, weil es mir wichtig ist, die Aufgaben zu erledigen, die ich erledigen muss. Und ich stelle fest, dass sie dort auch JSON-Parsing haben, was gut ist, da ich das tun muss, nachdem ich die HTTP-Anfrage gesendet habe, wofür ich die Bibliothek bekommen habe.

    – Goldesel

    26. Februar 2014 um 13:37 Uhr

  • @ Hack06 Danke für den Kommentar. Ich habe eine neue Antwort bereitgestellt, die diese jetzt ersetzt: stackoverflow.com/a/61177330/278976

    – Homer6

    12. April 2020 um 19:58 Uhr

1647079812 240 Wie machen Sie eine HTTP Anfrage mit C
Huhu

Es wird ein neuerer, weniger ausgereifter Curl-Wrapper namens entwickelt C++-Anfragen. Hier ist eine einfache GET-Anfrage:

#include <iostream>
#include <cpr.h>

int main(int argc, char** argv) {
    auto response = cpr::Get(cpr::Url{"http://httpbin.org/get"});
    std::cout << response.text << std::endl;
}

Es unterstützt eine Vielzahl von HTTP-Verben und Curl-Optionen. Es gibt mehr Nutzungsdokumentation Hier.

Haftungsausschluss: Ich bin der Betreuer dieser Bibliothek.

Aktualisierte Antwort für April 2020:

Ich hatte in letzter Zeit viel Erfolg mit cpp-httplib (Sowohl als Client als auch als Server). Es ist ausgereift und sein ungefährer Single-Thread-RPS liegt bei etwa 6k.

Auf mehr von der blutenden Kante gibt es ein wirklich vielversprechendes Framework, cpv-frameworkdas auf zwei Kernen etwa 180.000 RPS erreichen kann (und sich gut mit der Anzahl der Kerne skalieren lässt, da es auf dem Seestern Framework, das die schnellsten DBs der Welt antreibt, scylladb).

Allerdings ist das cpv-Framework noch relativ unausgereift; Daher empfehle ich für die meisten Anwendungen cpp-httplib.

Diese Empfehlung ersetzt meine vorherige Antwort (vor 8 Jahren).

  • Danke, werde es demnächst mal ausprobieren 😉

    – Hack06

    12. April 2020 um 20:42 Uhr

  • Ich mag den 1-Datei (5K-Zeilen ist ok)-Ansatz von cpp-httplib sehr. Hast du eine Vorstellung von seiner Leistung?

    – Hack06

    3. Mai 2020 um 15:44 Uhr

  • @Hack06 Der grobe Richtwert lag bei etwa 6000 Anfragen pro Sekunde (RPS).

    – Homer6

    10. Mai 2020 um 18:40 Uhr

  • Diese Bibliothek (cpp-httplib) funktioniert nicht unter Windows 8 … Die Fehlermeldungen sind auch nicht sehr hilfreich. Außerdem mag ich die Idee nicht, dass ich eine ca-bundle.crt für eine SSL-Verbindung benötigen muss. Für die Clientseite ist dies nicht erforderlich

    – Imtiaz Shakil Siddique

    28. März 2021 um 18:03 Uhr


  • Ich fühle mich verrückt, wenn ich von c# komme, wo eine einfache http-Anfrage sooo einfach ist, cpp-httplib wie andere, man muss durch so viele Reifen springen, nur um es dahin zu bringen, wo man einen einfachen https-Aufruf tätigen kann

    – ZackOfAllTrades

    4. November 2021 um 18:25 Uhr

1647079812 340 Wie machen Sie eine HTTP Anfrage mit C
Juzzlin

Wenn Sie eine C++-Lösung wünschen, könnten Sie verwenden Qt. Es hat eine QHttp-Klasse, die Sie verwenden können.

Sie können die überprüfen Dokumente:

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

Qt hat auch viel mehr zu bieten, als Sie in einer gewöhnlichen C++-App verwenden könnten.

  • Danke, werde es demnächst mal ausprobieren 😉

    – Hack06

    12. April 2020 um 20:42 Uhr

  • Ich mag den 1-Datei (5K-Zeilen ist ok)-Ansatz von cpp-httplib sehr. Hast du eine Vorstellung von seiner Leistung?

    – Hack06

    3. Mai 2020 um 15:44 Uhr

  • @Hack06 Der grobe Richtwert lag bei etwa 6000 Anfragen pro Sekunde (RPS).

    – Homer6

    10. Mai 2020 um 18:40 Uhr

  • Diese Bibliothek (cpp-httplib) funktioniert nicht unter Windows 8 … Die Fehlermeldungen sind auch nicht sehr hilfreich. Außerdem mag ich die Idee nicht, dass ich eine ca-bundle.crt für eine SSL-Verbindung benötigen muss. Für die Clientseite ist dies nicht erforderlich

    – Imtiaz Shakil Siddique

    28. März 2021 um 18:03 Uhr


  • Ich fühle mich verrückt, wenn ich von c# komme, wo eine einfache http-Anfrage sooo einfach ist, cpp-httplib wie andere, man muss durch so viele Reifen springen, nur um es dahin zu bringen, wo man einen einfachen https-Aufruf tätigen kann

    – ZackOfAllTrades

    4. November 2021 um 18:25 Uhr

Hier ist mein minimaler Wrapper um cURL, um eine Webseite einfach als Zeichenfolge abrufen zu können. Dies ist beispielsweise für Unit-Tests nützlich. Es ist im Grunde ein RAII-Wrapper um den C-Code.

Installieren Sie “libcurl” auf Ihrem Rechner yum install libcurl libcurl-devel oder gleichwertig.

Anwendungsbeispiel:

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

Klassenimplementierung:

#include <curl/curl.h>


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<CURLplusplus*>(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;
    }
};

993350cookie-checkWie machen Sie eine HTTP-Anfrage mit C++?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy