Comment faites - vous une requête HTTP avec C++?

Existe-t-il un moyen de faire facilement une requête HTTP avec C++? Plus précisément, je veux télécharger le contenu d'une page (une API) et vérifier le contenu pour voir s'il contient un 1 ou un 0. Est-il également possible de télécharger le contenu dans une chaîne?

210
demandé sur Patrick Hofman 2009-06-18 11:52:41

18 réponses

J'ai eu le même problème. libcurl est vraiment complète. Il y a un wrapper C++ curlpp qui pourrait vous intéresser lorsque vous demandez une bibliothèque C++. neon est une autre bibliothèque C intéressante qui supporte également webdav.

Curlpp semble naturel si vous utilisez C++. Il y a beaucoup d'exemples fournis dans la distribution source. Pour obtenir le contenu D'une URL, vous faites quelque chose comme ça (extrait d'exemples):

// 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();

Voir le répertoire examples dans curlpp source distribution , Il y a beaucoup de cas plus complexes.

Mes 2 cents ...

196
répondu neuro 2016-10-24 13:54:26

Code Windows:

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

Voici une bien meilleure implémentation:

#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);
}
98
répondu Software_Designer 2016-10-10 16:58:55

Sous Linux, j'ai essayé cpp-netlib, libcurl, curlpp, urdl, boost:: asio et considéré Qt (mais l'ai refusé en fonction de la licence). Tous ces éléments étaient incomplets pour cette utilisation, avaient des interfaces bâclées, avaient une mauvaise documentation, n'étaient pas maintenus ou ne supportaient pas https.

Ensuite, à la suggestion de https://stackoverflow.com/a/1012577/278976 , j'ai essayé POCO. Wow, j'aurais aimé avoir vu ça il y a des années. Voici un exemple de création D'un HTTP GET demande:

Http://xjia.heroku.com/2011/09/10/learning-poco-get-with-http/

POCO est gratuit, open source (licence boost). Et Non, Je n'ai aucune affiliation avec l'entreprise; j'aime vraiment leurs interfaces. Super boulot les gars (et les filles).

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

J'espère que cela aide quelqu'un... il m'a fallu trois jours pour essayer toutes ces bibliothèques.

33
répondu Homer6 2017-05-23 11:55:10

Il existe un wrapper curl plus récent et moins mature en cours de développement appelé C++ Requests . Voici une simple requête GET:

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

Il prend en charge une grande variété de verbes HTTP et d'options de curl. Il y a plus de documentation d'utilisation ici .

Disclaimer: je suis le mainteneur de cette bibliothèque .

24
répondu huu 2015-09-30 18:32:21

Comme vous voulez une solution c++, Vous pouvez utiliser Qt . Il a une classe QHttp que vous pouvez utiliser.

Vous pouvez vérifier les documents :

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

Qt a aussi beaucoup plus que vous pouvez utiliser dans une application c++ commune.

16
répondu Marcelo Santos 2015-03-05 21:29:17

LibCURL est une très bonne option pour vous. En fonction de ce que vous devez faire, le tutoriel devrait vous dire ce que vous voulez, en particulier pour la poignée facile. Mais, fondamentalement, vous pouvez le faire juste pour voir la source d'une page:

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

Je crois que cela entraînera l'impression du résultat sur stdout. Si vous voulez le gérer à la place - ce que, je suppose, vous le faites-vous devez définir la fonction CURL_WRITEFUNCTION. Tout cela est couvert dans le tutoriel curl lié ci-dessus.

14
répondu FreeMemory 2009-06-18 15:57:13

Voici mon wrapper minimal autour de cURL pour pouvoir simplement récupérer une page Web en tant que chaîne. Ceci est utile, par exemple, pour les tests unitaires. C'est essentiellement un wrapper RAII autour du code C.

Installer "libcurl" sur votre machine yum install libcurl libcurl-devel ou équivalent.

Exemple d'Utilisation:

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

Implémentation de classe:

#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;
    }
};
13
répondu Mark Lakata 2015-01-30 23:07:40

Avec cette réponse, je me réfère à la réponse de Software_Developer . En reconstruisant le code, j'ai trouvé que certaines parties sont obsolètes (gethostbyname()) ou ne fournit pas de gestion des erreurs (création de sockets, envoi de quelque chose) pour une opération.

Le code windows suivant est testé avec Visual Studio 2013 et Windows 8.1 64 bits ainsi que Windows 7 64 bits. Il ciblera une connexion TCP IPv4 avec le serveur Web de www.google.com.

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

Références:

La Dépréciation de gethostbyname

Valeur de Retour de socket()

La Valeur de Retour d'envoyer()

10
répondu Vinzenz 2017-05-23 10:31:38

Vous pouvez vérifier C++ REST SDK (nom de code "Casablanca"). http://msdn.microsoft.com/en-us/library/jj950081.aspx

Avec le SDK REST C++, vous pouvez plus facilement vous connecter aux serveurs HTTP à partir de votre application C++.

Exemple d'Utilisation:

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

Le SDK REST c++ est un projet Microsoft pour la communication client-Serveur Basée sur le cloud en code natif utilisant une conception D'API C++ asynchrone moderne.

10
répondu copperoxide 2018-03-14 09:47:22

C++ ne fournit aucun moyen de le faire directement. Cela dépendrait entièrement des plates-formes et des bibliothèques que vous avez.

Dans le pire des cas, vous pouvez utiliser la bibliothèque boost::asio pour établir une connexion TCP, envoyer les en-têtes HTTP (RFC 2616) et analyser les réponses directement. En regardant vos besoins d'application, c'est assez simple à faire.

6
répondu sybreon 2009-06-18 08:13:42

C et c++ n'ont pas de bibliothèque standard pour HTTP ou même pour les connexions socket. Au fil des ans, certaines bibliothèques portables ont été développées. Le plus largement utilisé, comme d'autres l'ont dit, est - libcurl.

Voici une Liste d'alternatives à libcurl (provenant du site Web de libcurl).

Aussi, pour Linux, ce est un simple client HTTP. Vous pouvez implémenter votre propre client HTTP GET simple, mais cela ne fonctionnera pas s'il existe une authentification ou des redirections ou si vous avez besoin de travailler derrière un proxy. Pour ces cas, vous avez besoin d'une bibliothèque complète comme libcurl.

Le code source avec libcurl, ce est le plus proche de ce que vous voulez (Libcurl a beaucoup de exemples). Regardez la fonction principale. Le contenu html sera copié dans le tampon, après une connexion réussie. Remplacez simplement parseHtml par votre propre fonction.

3
répondu kgiannakakis 2009-07-10 10:29:11

Vous pouvez utiliser la bibliothèqueembeddedRest . C'est une bibliothèque légère en-tête uniquement. Il est donc facile de l'inclure dans votre projet et il ne nécessite pas de compilation car il n'y a pas de fichiers .cpp.

Exemple de Demande de readme.md de 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;
}
3
répondu fnc12 2016-02-19 12:18:20

Voici un code C++11 (relativement) simple qui utilise libCURL pour télécharger le contenu D'une URL dans un std::vector<char>:

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);
}
2
répondu Drew Noakes 2014-11-13 13:34:50

Généralement, je recommanderais quelque chose de multi-plateforme comme cURL, POCO ou Qt. Cependant, voici un exemple de 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();
2
répondu Peter Tseng 2015-05-05 14:53:22

Le protocole HTTP est très simple, il est donc très simple d'écrire un client HTTP. Voici un

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

Il utilise HTTP GET pour récupérer un fichier à partir d'un serveur web, le serveur et le fichier sont des paramètres de ligne de commande. Le fichier distant est enregistré dans une copie locale.

Avertissement: je suis l'auteur

Modifier: URL modifiée

2
répondu Pedro Vicente 2016-12-29 19:42:55

Notez que cela ne nécessite pas libcurl, Windows.h, ou WinSock! Pas de compilation de bibliothèques, pas de configuration de projet, etc. J'ai ce code qui fonctionne dans Visual Studio 2017 C++ sur 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();

Je viens de comprendre comment faire cela, car je voulais un simple script D'accès API, des bibliothèques comme libcurl me causaient toutes sortes de problèmes (même quand je suivais les instructions...), et c'est juste trop bas niveau et compliqué.

Je ne suis pas tout à fait sûr de tous les IStream lecture du code (en particulier la condition while-n'hésitez pas à corriger / améliorer), mais bon, cela fonctionne, sans tracas! (Il est logique pour moi que, puisque j'ai utilisé un blocage (synchrone) appel , c'est bien, que {[1] } serait toujours > 0U jusqu'à ce que le flux (ISequentialStream?) est fini d'être lu, mais qui sait.)

Voir aussi: noms d'URL et Asynchrone Protocole Enfichable Référence

2
répondu Andrew 2018-08-22 09:43:34

Bien qu'un peu en retard. Vous pouvez préférer https://github.com/Taymindis/backcurl .

Il vous permet de faire un appel http sur le développement C++ mobile. Convient pour le développement de jeux mobiles

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
1
répondu minika woon 2017-06-14 01:48:38

Vous pouvez utiliser ACE pour le faire:

#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;
}
0
répondu inbaly 2015-03-11 14:10:17