Eine HTTP-Webseite ansprechen?



  • auf den meisten systemen wird die libcurl installiert sein.



  • Hallo.

    Vielen Dank für eure Antworten.

    Ich habe bereits etwas aus dem Magazin zusammengebastelt, was bis jetzt auch funktioniert. Leider kann der socket keine SSL Verbindungen verwalten, was quasi bedeutet, ich kann die Arbeiten doppelt machen, sofern ich überhaupt eine SSLSocket-Klasse finde.

    Da ich bei PHP soetwas wie CURL schoneinmal gehört habe, denke ich, dass es gut wäre, das bei C++ auch mal auszuprobieren. Scheinbar ist curllib aber nicht auf dem Server installiert und ich habe als Anfänger ziemliche Probleme, eine GCC Library auf dem mir unbekannten System zu installieren.

    Ist cUrlLib oder die anderen genannten Libraries in der Lage, folgende Aktionen durchzuführen:
    1. Aufrufen einer beliebigen URL (HTTP ODER HTTPS!)
    2. Dabei alle Weiterleitungen (301, 302) korrekt zu behandeln sowie ein Weiterleitungslimit von 50 Weiterleitungen zu beachten
    3. Einen eigenen User-Agent zu senden
    4. Den HTTP-Statuscode korrekt zu werten und bei einem 4xx oder 5xx Fall einen False-Boolean zu erwidern
    5. Den korrekten Inhalt der Seite auswerten (sprich: als benutzbaren String
    zurückgeben, ohne die Chunked-Part-Segmentnummern)

    Hat jemand, der sich mit cUrlLib gut auskennt zufälligerweiße einen Beispielcode da?



  • blackdrake schrieb:

    Scheinbar ist curllib aber nicht auf dem Server installiert und ich habe als Anfänger ziemliche Probleme, eine GCC Library auf dem mir unbekannten System zu installieren.

    Was für eine Distro läuft denn dort? Vielleicht hilft Dir schon ein simples "apt-get install libcurl3-dev" oder so.

    Ist cUrlLib oder die anderen genannten Libraries in der Lage, folgende Aktionen durchzuführen:[…]

    Ja, ohne weiteres.



  • nman schrieb:

    Was für eine Distro läuft denn dort? Vielleicht hilft Dir schon ein simples "apt-get install libcurl3-dev" oder so.

    Hallo. Vielen Dank für die Antwort. Der Befehl hat auf dem Debian System korrekt und ohne Probleme funktioniert. Hätte gar nicht gedacht, dass das so einfach geht, da auf der cUrlLib Seite überall nur das manuelle Compilieren beschrieben war.

    Ich bin jetzt erstmal dabei, die unzähligen CURL-Optionen durchzuprobieren und meine Funktion zusammenzubasteln. Ich melde mich nochmal, wenn ich fertig bin oder Probleme habe. Vielen Dank für eure Antworten.

    Gruß
    blackdrake



  • So, folgenden Code habe ich jetzt und es läuft alles wunderbar!

    const char* USER_AGENT = "Mein Crawler Name";
    
    #include <curl/curl.h>
    
     // This is the writer call back function used by curl
     static int writer(char *data, size_t size, size_t nmemb, std::string *buffer)
    {
         // What we will return
         int result = 0;
    
         // Is there anything in the buffer?
         if (buffer != NULL)
         {
              // Append the data to the buffer
              buffer->append(data, size * nmemb);
    
              // How much did we write?
              result = size * nmemb;
         }
    
         return result;
    }
    
    void http_curl (char* url) {
         CURL *curl;
    
         curl = curl_easy_init();
         if(curl) {
              // Infos: http://us3.php.net/curl_setopt
    
              // URL übergeben
              curl_easy_setopt(curl, CURLOPT_URL, url);
    
              // Keine Kopfzeile einblenden
              curl_easy_setopt(curl, CURLOPT_HEADER, false);
    
              // Verbindung danach beenden
              curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, true);
    
              // Pufferoptionen
              char errorBuffer[CURL_ERROR_SIZE];
              curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
              curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
              string buffer;
              curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
    
              // Benutzerdefinierter User-Agent-Name
              curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);
    
              // Einen Timeout setzen
              curl_easy_setopt(curl, CURLOPT_TIMEOUT, 180);
    
              // Weiterleitungen beachten, aber nur max. 50x
              curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true);
              curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50);
    
              // Einen HTTP-Fehler-Statuscode beachten
              curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
    
              // SSL-Zertifikate nicht prüfen (Warnung! Sicherheitslücke)
              // http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html
              curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
              curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
    
              // Abfrage ausführen und Resultat speichern
              CURLcode res;
              res = curl_easy_perform(curl);
    
              // Clean up
              curl_easy_cleanup(curl);
    
              // Alles OK?
              if (res == CURLE_OK)
              {
                   cout << buffer << "\n";
              }
              else
              {
                   cout << "Error: [" << res << "] - " << errorBuffer;
              }
         }
    }
    

    (Habe das Beispiel mal gepostet in http://devboard.viathinksoft.de/viewtopic.php?f=34&t=791 )

    2 Fragen habe ich aber noch:
    1. Muss das Objekt curl noch irgendwie freigegeben werden? In PHP gab es dafür curl_close(), was jedoch bei C++ nicht existiert.
    2. Wird die Verbindung korrekt beendet? Obwohl ich CURLOPT_FORBID_REUSE verwende, kommt der Header "Connection: close" scheinbar nicht beim Client an (ansonsten würde das dort befindliche PHP-Script den Wert $_SERVER['HTTP_CONNECTION'] == 'close'; erhalten, was hier aber nicht der Fall ist. Wie regelt cURL das ganze dann mit dem Beenden der alten Verbindungen?

    (Da das ganze in einem Daemon läuft, darf ich mir nicht erlauben, dass tote Verbindungen beibehalten werden oder ein Speicherleck besteht, deswegen frage ich sicherheitshalber nocheinmal nach)

    Gruß
    blackdrake



  • Zu Frage 1:
    Das Objekt wird mit

    curl = curl_easy_init();
    

    initialisiert, und mit

    curl_easy_cleanup(curl);
    

    freigegeben. Was soll da noch nötig sein?



  • OK, im Manual stand eben nur etwas von "Close session", was für mich nicht nz gaeindeutig war. Da es aber scheinbar kein curl_close() wie beim PHP-Derivat gibt, wird der restliche Speicher ja wahrscheinlich von selbst freigegeben.

    Gruß
    blackdrake



  • Weiß jemand ob es irgendwo eine Art Tutorial für die Verwendung der libcurl gibt?

    Habe bisher immer mit der WININET gearbeitet, will jetzt aber auf eine plattformunabhängige Bibliothek umstellen.
    Ich nehme mal an, da ist die libcurl noch die beste Wahl. Oder gibt es inzwischen etwas neueres?



  • libcurl ist immer noch ziemlich gut. Und zur Doku: Was brauchst Du, was hier nicht zu finden ist? http://curl.haxx.se/libcurl/



  • blackdrake schrieb:

    So, folgenden Code habe ich jetzt und es läuft alles wunderbar!

    He danke fuer das Beipiel, gerade noch ein main und stl_libs dazu gefriemelt und ausprobiert, funktioniert einwandfrei! TOP 😉
    graetz 😃


Anmelden zum Antworten