Frage

Gibt es eine Möglichkeit, einfach eine HTTP-Anforderung mit C ++ zu machen? Insbesondere möchte ich den Inhalt einer Seite zum Download (eine API) und die Inhalte überprüfen, um zu sehen, ob es enthält eine 1 oder eine 0. Ist es auch möglich, den Inhalt in einen String herunterladen?

War es hilfreich?

Lösung

Ich hatte das gleiche Problem. Libcurl ist wirklich abgeschlossen. Es ist eine C ++ Wrapper curlpp die Sie interessieren könnten, wie Sie für eine C ++ Bibliothek stellen. neon ist eine weitere interessante C-Bibliothek, die auch WebDAV .

curlpp scheint natürlich, wenn Sie C ++ verwenden. Es gibt viele Beispiele in der Source-Distribution zur Verfügung gestellt. Um den Inhalt einer URL erhalten Sie tun so etwas (extrahiert aus den Beispielen):

// 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://www.wikipedia.org"));

string asAskedInQuestion = os.str();

Sehen Sie das examples Verzeichnis in curlpp Quellenverteilung , gibt es eine Menge von komplexeren Fällen auch als mit curlpp einfach komplette minimal ein rel="noreferrer">.

my 2 cents ...

Andere Tipps

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 Umsetzung:

#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('/');
    if (n != string::npos)
    {
        serverName = url.substr(0,n);
        filepath = url.substr(n);
        n = filepath.rfind('/');
        filename = filepath.substr(n+1);
    }

    else
    {
        serverName = url;
        filepath = "/";
        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);
}

Unter Linux habe ich versucht, cpp-netlib, libcurl, curlpp, Urdl boost :: asio und betrachtet Qt (aber lehnte ab auf der Grundlage der Lizenz). Alle diese waren entweder unvollständig für diesen Einsatz hatte schlampig Schnittstellen, hatte schlechte Dokumentation, waren nicht gewartet oder nicht https unterstützen.

Dann auf Anregung von https://stackoverflow.com/a/1012577/278976 , habe ich versucht POCO . Wow, ich wünschte, ich hätte vor Jahren gesehen. Hier ist ein Beispiel zur Herstellung einer HTTP-GET-Anfrage:

http://xjia.heroku.com / 2011/09/10 / Lernen-poco-get-mit-http /

POCO ist kostenlos, Open Source (Boost-Lizenz). Und nein, ich habe keine Verbindung mit dem Unternehmen; Ich mag nur wirklich ihre Schnittstellen. Great job Jungs (und Mädels).

http://pocoproject.org/download/index.html

Hope dies hilft jemand ... es hat mich drei Tage, um alle diese Bibliotheken ausprobieren.

Es gibt einen neuen, weniger reifen curl Wrapper entwickelt genannt 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 Nutzungs Dokumentation hier .

Disclaimer:. Ich bin der Maintainer dieser Bibliothek

Libcurl ist eine ziemlich gute Wahl für Sie. Je nachdem, was Sie tun müssen, die Tutorial sollten Sie sagen, was Sie wollen, die speziell für den einfachen Griff. Aber im Grunde, könnten Sie dies tun, nur 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 veranlassen, dass das Ergebnis auf der Standardausgabe gedruckt. Wenn Sie es stattdessen behandeln wollen - was, ich nehme an, Sie tun - müssen Sie die CURL_WRITEFUNCTION einzustellen. Alles das ist in den Curl-Tutorial oben verlinkten abgedeckt.

Wie Sie eine C ++ Lösung wollen, könnten Sie verwenden Qt . Es hat eine QHttp Klasse, die Sie verwenden können.

Sie können prüfen, die docs :

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

Qt hat auch viel mehr dafür, dass Sie in einem gemeinsamen C ++ App nutzen könnten.

Hier ist mein minimal Wrapper um cURL der Lage zu sein, nur eine Webseite als String zu holen. Dies ist nützlich, zum Beispiel für Komponententests. Es ist im Grunde ein RAH-Wrapper um den C-Code.

Install "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");

Klasse Umsetzung:

#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;
    }
};

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

Mit dem C ++ REST SDK können Sie mehr verbinden leicht zu HTTP-Servern aus der C ++ App.

Anwendungsbeispiel:

#include <iostream>
#include <cpprest/http_client.h>

using namespace web::http;                  // Common HTTP functionality
using namespace web::http::client;          // HTTP client features

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

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

    // working with json
    response = client.request(methods::GET, "/get").get();
    std::cout << "url: " << response.extract_json().get()[U("url")] << "\n";
}

Der C ++ REST SDK ist ein Microsoft-Projekt für Cloud-basierte Client-Server-Kommunikation in nativen Code ein modernes asynchrones C ++ API-Design.

Mit dieser Antwort, die ich auf der Seite Antwort verweisen von Software_Developer . Durch den Code Wiederaufbau fand ich, dass einige Teile sind veraltete (gethostbyname()) oder bietet keine Fehlerbehandlung (Schaffung von Steckdosen, etwas zu senden) für eine Operation.

Das folgende Fenster Code mit Visual Studio 2013 getestet und Windows 8.1 64-Bit sowie Windows 7 64-bit. Es wird eine IPv4-TCP-Verbindung mit dem Web-Server von www.google.com Ziel.

#include <winsock2.h>
#include <WS2tcpip.h>
#include <windows.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
    int main (){
    // Initialize Dependencies to the Windows Socket.
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
        cout << "WSAStartup failed.\n";
        system("pause");
        return -1;
    }

    // We first prepare some "hints" for the "getaddrinfo" function
    // to tell it, that we are looking for a IPv4 TCP Connection.
    struct addrinfo hints;
    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;          // We are targeting IPv4
    hints.ai_protocol = IPPROTO_TCP;    // We are targeting TCP
    hints.ai_socktype = SOCK_STREAM;    // We are targeting TCP so its SOCK_STREAM

    // Aquiring of the IPv4 address of a host using the newer
    // "getaddrinfo" function which outdated "gethostbyname".
    // It will search for IPv4 addresses using the TCP-Protocol.
    struct addrinfo* targetAdressInfo = NULL;
    DWORD getAddrRes = getaddrinfo("www.google.com", NULL, &hints, &targetAdressInfo);
    if (getAddrRes != 0 || targetAdressInfo == NULL)
    {
        cout << "Could not resolve the Host Name" << endl;
        system("pause");
        WSACleanup();
        return -1;
    }

    // Create the Socket Address Informations, using IPv4
    // We dont have to take care of sin_zero, it is only used to extend the length of SOCKADDR_IN to the size of SOCKADDR
    SOCKADDR_IN sockAddr;
    sockAddr.sin_addr = ((struct sockaddr_in*) targetAdressInfo->ai_addr)->sin_addr;    // The IPv4 Address from the Address Resolution Result
    sockAddr.sin_family = AF_INET;  // IPv4
    sockAddr.sin_port = htons(80);  // HTTP Port: 80

    // We have to free the Address-Information from getaddrinfo again
    freeaddrinfo(targetAdressInfo);

    // Creation of a socket for the communication with the Web Server,
    // using IPv4 and the TCP-Protocol
    SOCKET webSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (webSocket == INVALID_SOCKET)
    {
        cout << "Creation of the Socket Failed" << endl;
        system("pause");
        WSACleanup();
        return -1;
    }

    // Establishing a connection to the web Socket
    cout << "Connecting...\n";
    if(connect(webSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr)) != 0)
    {
        cout << "Could not connect";
        system("pause");
        closesocket(webSocket);
        WSACleanup();
        return -1;
    }
    cout << "Connected.\n";

    // Sending a HTTP-GET-Request to the Web Server
    const char* httpRequest = "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n";
    int sentBytes = send(webSocket, httpRequest, strlen(httpRequest),0);
    if (sentBytes < strlen(httpRequest) || sentBytes == SOCKET_ERROR)
    {
        cout << "Could not send the request to the Server" << endl;
        system("pause");
        closesocket(webSocket);
        WSACleanup();
        return -1;
    }

    // Receiving and Displaying an answer from the Web Server
    char buffer[10000];
    ZeroMemory(buffer, sizeof(buffer));
    int dataLen;
    while ((dataLen = 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;
        }
    }

    // Cleaning up Windows Socket Dependencies
    closesocket(webSocket);
    WSACleanup();

    system("pause");
    return 0;
}

Referenzen:

Deprecation von gethostbyname

Rückgabewert der Buchse ()

Rückgabewert von Sende ()

C ++ bietet keine Möglichkeit, es direkt zu tun. Es wäre ganz davon abhängen, welche Plattformen und Bibliotheken, die Sie haben.

Im schlimmsten Fall können Sie die boost :: asio Bibliothek verwenden, um eine TCP-Verbindung aufzubauen, die HTTP-Header senden (RFC 2616), und die Antworten direkt analysieren. Ein Blick auf Ihre Anwendung benötigt, ist dies einfach genug zu tun.

C und C ++ nicht über eine Standard-Bibliothek für HTTP oder sogar für Socket-Verbindungen. Im Laufe der Jahre haben sich einige portable Bibliotheken entwickelt. Die am weitesten verbreiteten, wie andere gesagt haben, ist Libcurl .

Hier ist eine Liste von Alternativen zu Libcurl (von der Website des Libcurl kommen ).

Auch für Linux, this ist ein einfaches HTTP-Client. Sie könnten Ihren eigenen einfachen HTTP-GET-Client implementieren, aber das wird nicht funktionieren, wenn es die Authentifizierung oder Umleitungen beteiligt oder wenn Sie hinter einem Proxy arbeiten müssen. Für diese Fälle müssen Sie eine ausgewachsene Bibliothek wie Libcurl.

Für Quellcode mit libcurl, diese ist die am nächsten, was Sie wollen (libcurl hat viele Beispiele rel="nofollow). Schauen Sie sich die Hauptfunktion. Der HTML-Inhalt wird in den Puffer kopiert werden, nach einer erfolgreichen Verbindung. Ersetzen Sie einfach parseHtml mit Ihrer eigenen Funktion.

Sie können mit embeddedRest Bibliothek. Es ist leicht Kopf nur Bibliothek. So ist es einfach, es zu einem Projekt gehört und es nicht Kompilation Ursache gibt es noch keine .cpp Dateien in es benötigt.

Anfrage Beispiel von readme.md aus Repo:

#include "UrlRequest.hpp"

//...

UrlRequest request;
request.host("api.vk.com");
const auto countryId=1;
const auto count=1000;
request.uri("/method/database.getCities",{
    {"lang","ru"},
    {"country_id",countryId},
    {"count",count},
    {"need_all","1"},
});
request.addHeader("Content-Type: application/json");
auto response=std::move(request.perform());
if(response.statusCode()==200){
  cout<<"status code = "<<response.statusCode()<<", body = *"<<response.body()<<"*"<<endl;
}else{
  cout<<"status code = "<<response.statusCode()<<", description = "<<response.statusDescription()<<endl;
}

Das HTTP-Protokoll ist sehr einfach, so ist es sehr einfach, ein HTTP-Client zu schreiben. Hier ist ein

https://github.com/pedro-vicente/lib_netsockets

Es verwendet HTTP GET eine Datei von einem Web-Server abgerufen werden, beide Server und Dateibefehlszeilenparameter sind. Die Remote-Datei auf eine lokale Kopie gespeichert wird.

Disclaimer: Ich bin der Autor

EDIT: bearbeiteten URL

Hier ist ein Code, der ohne die Notwendigkeit, arbeiten alle 3rd-Party-Bibliothek zu verwenden: Definieren Sie zunächst Ihre Gateway, Benutzer, Passwort und alle anderen Parameter, die Sie auf diesen speziellen Server senden müssen.

#define USERNAME "user"
#define PASSWORD "your password"
#define GATEWAY "your gateway"

Hier ist der Code selbst:

HINTERNET hOpenHandle, hResourceHandle, hConnectHandle;
const TCHAR* szHeaders = _T("Content-Type:application/json; charset=utf-8\r\n");


hOpenHandle = InternetOpen(_T("HTTPS"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (hOpenHandle == NULL)
{
    return false;
}


hConnectHandle = InternetConnect(hOpenHandle,
    GATEWAY,
    INTERNET_DEFAULT_HTTPS_PORT,
    NULL, NULL, INTERNET_SERVICE_HTTP,
    0, 1);

if (hConnectHandle == NULL)
{
    InternetCloseHandle(hOpenHandle);
    return false;
}


hResourceHandle = HttpOpenRequest(hConnectHandle,
    _T("POST"),
    GATEWAY,
    NULL, NULL, NULL, INTERNET_FLAG_SECURE | INTERNET_FLAG_KEEP_CONNECTION,
    1);

if (hResourceHandle == NULL)
{
    InternetCloseHandle(hOpenHandle);
    InternetCloseHandle(hConnectHandle);
    return false;
}

InternetSetOption(hResourceHandle, INTERNET_OPTION_USERNAME, (LPVOID)USERNAME, _tcslen(USERNAME));
InternetSetOption(hResourceHandle, INTERNET_OPTION_PASSWORD, (LPVOID)PASSWORD, _tcslen(PASSWORD));

std::string buf;
if (HttpSendRequest(hResourceHandle, szHeaders, 0, NULL, 0))
{
    while (true)
    {
        std::string part;
        DWORD size;
        if (!InternetQueryDataAvailable(hResourceHandle, &size, 0, 0))break;
        if (size == 0)break;
        part.resize(size);
        if (!InternetReadFile(hResourceHandle, &part[0], part.size(), &size))break;
        if (size == 0)break;
        part.resize(size);
        buf.append(part);
    }
}

if (!buf.empty())
{
    // Get data back
}

InternetCloseHandle(hResourceHandle);
InternetCloseHandle(hConnectHandle);
InternetCloseHandle(hOpenHandle);

Das sollte auf einer Win32-API-Umgebung arbeiten.

Hier ist ein Beispiel .

Hier finden Sie einige (relativ) einfachen C ++ 11-Code, der Libcurl verwendet eine URL-Inhalte in einem std::vector<char> zum Download:

http_download.hh

# pragma once

#include <string>
#include <vector>

std::vector<char> download(std::string url, long* responseCode = nullptr);

http_download.cc

#include "http_download.hh"

#include <curl/curl.h>
#include <sstream>
#include <stdexcept>

using namespace std;

size_t callback(void* contents, size_t size, size_t nmemb, void* user)
{
  auto chunk = reinterpret_cast<char*>(contents);
  auto buffer = reinterpret_cast<vector<char>*>(user);

  size_t priorSize = buffer->size();
  size_t sizeIncrease = size * nmemb;

  buffer->resize(priorSize + sizeIncrease);
  std::copy(chunk, chunk + sizeIncrease, buffer->data() + priorSize);

  return sizeIncrease;
}

vector<char> download(string url, long* responseCode)
{
  vector<char> data;

  curl_global_init(CURL_GLOBAL_ALL);
  CURL* handle = curl_easy_init();
  curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
  curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, callback);
  curl_easy_setopt(handle, CURLOPT_WRITEDATA, &data);
  curl_easy_setopt(handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
  CURLcode result = curl_easy_perform(handle);
  if (responseCode != nullptr)
    curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, responseCode);
  curl_easy_cleanup(handle);
  curl_global_cleanup();

  if (result != CURLE_OK)
  {
    stringstream err;
    err << "Error downloading from URL \"" << url << "\": " << curl_easy_strerror(result);
    throw runtime_error(err.str());
  }

  return move(data);
}

Generell würde ich etwas Cross-Plattform wie cURL, POCO oder Qt empfehlen. Doch hier ist ein Beispiel für Windows !:

#include <atlbase.h>
#include <msxml6.h>
#include <comutil.h> // _bstr_t

HRESULT hr;
CComPtr<IXMLHTTPRequest> request;

hr = request.CoCreateInstance(CLSID_XMLHTTP60);
hr = request->open(
    _bstr_t("GET"),
    _bstr_t("https://www.google.com/images/srpr/logo11w.png"),
    _variant_t(VARIANT_FALSE),
    _variant_t(),
    _variant_t());
hr = request->send(_variant_t());

// get status - 200 if succuss
long status;
hr = request->get_status(&status);

// load image data (if url points to an image)
VARIANT responseVariant;
hr = request->get_responseStream(&responseVariant);
IStream* stream = (IStream*)responseVariant.punkVal;
CImage *image = new CImage();
image->Load(stream);
stream->Release();

Beachten Sie, dass dies nicht erforderlich ist Libcurl, Windows.h oder WinSock! Keine Sammlung von Bibliotheken, keine Projektkonfiguration, usw. ich diesen Code habe in Visual Studio 2017 c ++ arbeitet unter Windows 10:

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

#include <urlmon.h>
#include <sstream>

using namespace std;

...

IStream* stream;
//Also works with https URL's - unsure about the extent of SSL support though.
HRESULT result = URLOpenBlockingStream(0, "http://google.com", &stream, 0, 0);
if (result != 0)
{
    return 1;
}
char buffer[100];
unsigned long bytesRead;
stringstream ss;
stream->Read(buffer, 100, &bytesRead);
while (bytesRead > 0U)
{
    ss.write(buffer, (long long)bytesRead);
    stream->Read(buffer, 100, &bytesRead);
}
stream.Release();
string resultString = ss.str();

Ich habe herausgefunden, wie dies zu tun, wie ich einen einfachen API-Zugriff Skript wollte, Bibliotheken wie Libcurl verursacht wurden mich alle Arten von Problemen (auch wenn ich die Anweisungen gefolgt ...) und WinSock ist einfach zu niedrig- Ebene und kompliziert.

Ich bin nicht ganz sicher über all die IStream Code Lesen (vor allem die während Zustand - fühlen sie sich frei zu korrigieren / verbessern), aber hey, es funktioniert , stressfrei! (Es macht Sinn für mich, dass, da habe ich eine Blockierung (synchron) nennt , das ist in Ordnung, wäre das bytesRead immer> 0-HE bis zum Strom ( ISequentialStream ?) gelesen wird beendet, aber wer weiß.)

Siehe auch: URL Moniker und Asynchronous Pluggable-Protokoll-Referenz

Obwohl ein wenig spät. Sie können es vorziehen, https://github.com/Taymindis/backcurl .

Es ermöglicht Ihnen, http Anruf auf mobilen c ++ Entwicklung zu tun. Geeignet für Mobile Spiel Entwicklung

bcl::init(); // init when using

bcl::execute<std::string>([&](bcl::Request *req) {
    bcl::setOpts(req, CURLOPT_URL , "http://www.google.com",
             CURLOPT_FOLLOWLOCATION, 1L,
             CURLOPT_WRITEFUNCTION, &bcl::writeContentCallback,
             CURLOPT_WRITEDATA, req->dataPtr,
             CURLOPT_USERAGENT, "libcurl-agent/1.0",
             CURLOPT_RANGE, "0-200000"
            );
}, [&](bcl::Response * resp) {
    std::string ret =  std::string(resp->getBody<std::string>()->c_str());
    printf("Sync === %s\n", ret.c_str());
});


bcl::cleanUp(); // clean up when no more using

Wenn Sie sich für eine HTTP-Client-Bibliothek in C ++ suchen, die in mehreren Plattformen (Linux, Windows und Mac) für das Konsumieren von Restful Web Service unterstützt wird. Sie können unter Optionen.

  1. QT Network Library - Ermöglicht die Anwendung Netzwerkanfragen zu senden und empfangen Antworten
  2. C ++ REST SDK - Eine aufkommende Dritt HTTP-Bibliothek mit PPL Unterstützung
  3. Libcurl -. Es ist wahrscheinlich eines der am meisten verwendeten http lib in der nativen Welt

Sie können ACE verwenden, um dies zu tun:

#include "ace/SOCK_Connector.h"

int main(int argc, ACE_TCHAR* argv[])
{
    //HTTP Request Header
    char* szRequest = "GET /video/nice.mp4 HTTP/1.1\r\nHost: example.com\r\n\r\n"; 
    int ilen = strlen(szRequest);

    //our buffer
    char output[16*1024];

    ACE_INET_Addr server (80, "example.com");
    ACE_SOCK_Stream peer;
    ACE_SOCK_Connector connector;
    int ires = connector.connect(peer, server);
    int sum = 0;
    peer.send(szRequest, ilen);
    while (true)
    {
        ACE_Time_Value timeout = ACE_Time_Value(15);
        int rc = peer.recv_n(output, 16*1024, &timeout);
        if (rc == -1)
        {
            break;
        }
        sum += rc;
    }
    peer.close();
    printf("Bytes transffered: %d",sum);

    return 0;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top