คุณสร้างคำขอ HTTP ด้วย C ++ ได้อย่างไร


258

มีวิธีใดที่จะทำให้การร้องขอ HTTP ด้วย C ++ ง่ายขึ้นไหม โดยเฉพาะฉันต้องการดาวน์โหลดเนื้อหาของหน้า (API) และตรวจสอบเนื้อหาเพื่อดูว่ามันมี 1 หรือ 0 มันเป็นไปได้ไหมที่จะดาวน์โหลดเนื้อหาลงในสตริง


1
ไม่ปัจจุบันยังไม่มีการสนับสนุนในตัวผ่านภาษาหรือไลบรารีมาตรฐานสำหรับระบบเครือข่าย แต่มีเครือข่าย TS N4370 ฉันยัง VTC ต้องการคำถามนี้เพราะมันดึงดูดคำแนะนำห้องสมุด

แล้ว BoostBeast ล่ะ?
twocrush

คำตอบ:


249

ผมมีปัญหาเหมือนกัน. libcurlเสร็จสมบูรณ์จริงๆ มีcurlpp ของ C ++ ที่คุณอาจสนใจในขณะที่ขอไลบรารี C ++ นีออนเป็นอีกหนึ่งห้องสมุด C ที่น่าสนใจที่ยังสนับสนุนWebDAV

curlpp ดูเหมือนเป็นธรรมชาติถ้าคุณใช้ C ++ มีตัวอย่างมากมายในการแจกจ่ายแหล่งที่มา ในการรับเนื้อหาของ URL คุณต้องทำสิ่งนั้น (แยกจากตัวอย่าง):

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

ดูexamplesไดเรกทอรีกระจายแหล่งที่มา curlppมีมากในกรณีที่ซับซ้อนมากขึ้นเช่นเดียวกับความเรียบง่ายสมบูรณ์น้อยที่สุดหนึ่งใช้ curlpp

2 เซ็นต์ของฉัน ...


1
ดูเหมือนว่าเวอร์ชันล่าสุดจะใช้งานไม่ได้ใน mac .. มีบางอย่างสับสนกับ config.h เมื่อเชื่อมโยงกับไลบรารี
eugene

1
ฉันไม่สามารถรวบรวมข้างต้น อย่างไรก็ตามการแทนที่os << myRequest.perform();ด้วยmyRequest.setOpt( new curlpp::options::WriteStream( &os ) ); myRequest.perform();ผลลัพธ์ที่ให้ ตรวจสอบให้แน่ใจว่าไม่ได้ใช้http://example.comสิ่งนี้จะส่งคืนหน้าว่าง http://www.wikipedia.orgดีกว่าการใช้งานเช่น
Zane

4
คุณจะสร้าง curlpp ใน MSVS ได้อย่างไร ฉันไม่สามารถทำงานได้ :(
mr5

2
ฉันไม่เห็นด้วยกับการแก้ไขล่าสุดโดย @ ryan-sam เห็นได้ชัดว่ามันเป็นความตั้งใจของผู้เขียนที่จะเขียน "webdav" และไม่ใช่การพัฒนาเว็บเนื่องจากไลบรารีที่กำหนดนั้นถูกสร้างขึ้นอย่างชัดเจนสำหรับ "การดำเนินการ HTTP และ WebDAV"
Bostrot

2
@bostrot: ใช่ว่าฉันหมายถึงอะไร ฉันย้อนกลับและเพิ่มลิงค์ฉันคิดว่าคนคิดว่าฉันเขียน webdev ช่างเป็นเรื่องที่น่าเสียดาย :)
ประสาท

115

รหัส 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;
}

นี่คือการดำเนินการที่ดีขึ้นมาก:

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

ลองใช้รหัสนี้ใน Windows Vista ที่คอมไพล์ด้วย Dev-C ++ เวอร์ชั่น 4.9.9.2 ฉันให้ข้อผิดพลาดจำนวนมากเมื่อทำการเชื่อมโยง: [Linker error] การอ้างอิงที่ไม่ได้ระบุไปยัง `WSAStartup @ 8 '
Expanding-Dev

4
@ Expanding-Dev เฉพาะ MSVC (visual studio) เข้าใจ "pragma comment" หากคุณใช้สิ่งอื่นคุณต้องลิงก์ "ws2_32.lib" ด้วยตนเอง (เช่นไลบรารีอื่น ๆ )
Navin

24
@JuanLuisSoldi ฉันคิดว่าคุณจำเป็นต้องเป็น Windows dev เพื่อชื่นชม "ความงาม" ของรหัสนี้ ...
static_rtti

สิ่งที่ควรได้รับ (ใช้ recv) ที่นี่? ฉันกำลังพูดพล่อยๆมากเป็นเอาท์พุท นอกจากนี้ทำไมคุณใส่สิ่งที่คุณทำในการส่งบัฟเฟอร์ (เช่นGET / HTTP/1.1.1/... etc)? ฉันจะหาวิธีจัดรูปแบบสิ่งที่ฉันส่งได้อย่างไร
LazerSharks

43

อัปเดต 2020:ฉันมีคำตอบใหม่ที่แทนที่สิ่งนี้ตอนนี้อายุ 8 ปีหนึ่งคำตอบ: https://stackoverflow.com/a/61177330/278976

บน Linux ฉันพยายาม cpp-netlib, libcurl, curlpp, urdl, boost :: asio และพิจารณา Qt (แต่เปิดใช้งานตามใบอนุญาต) สิ่งเหล่านี้ทั้งหมดไม่สมบูรณ์สำหรับการใช้งานนี้มีอินเทอร์เฟซที่เลอะเทอะมีเอกสารที่ไม่ดีไม่มีการระบายหรือไม่สนับสนุน https

จากนั้นตามคำแนะนำของhttps://stackoverflow.com/a/1012577/278976ฉันลอง POCO ว้าวฉันหวังว่าฉันจะได้เห็นเมื่อหลายปีก่อน นี่คือตัวอย่างของการทำคำขอ HTTP GET กับ POCO:

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

POCO ฟรีโอเพนซอร์ส และไม่ฉันไม่มีส่วนเกี่ยวข้องกับ บริษัท ฉันชอบอินเทอร์เฟซของพวกเขาจริงๆ พวกงานที่ยอดเยี่ยม (และ gals)

https://pocoproject.org/download.html

หวังว่านี่จะช่วยใครซักคน ... ใช้เวลาสามวันในการลองใช้ห้องสมุดทั้งหมดเหล่านี้


1
นี่คือตัวอย่างเพิ่มเติม: github.com/pocoproject/poco/blob/develop/Net/samples/httpget/…
Homer6

2
ฉันเพิ่งดาวน์โหลด Poco ตามคำแนะนำของคุณ ฉันต้องการแสงบางอย่างที่สร้างขึ้นบน STL และเพิ่มแทนที่จะเขียนใหม่มาก รวมทั้งฉันไม่ได้เป็นแฟนของ CppUnit และโดยเฉพาะอย่างยิ่งการทดสอบความเกลียดชังที่เรียกใช้กับบิลด์และไม่คาดหวังว่าจะต้องทดสอบไลบรารีของพวกเขาเมื่อฉันสร้างมันขึ้นมา
CashCow

มันใหญ่ไปหน่อย อย่างไรก็ตามคุณสามารถปิดใช้งานการสร้างการทดสอบและตัวอย่าง (หรือไลบรารีที่แบ่งใช้) ด้วยการกำหนดค่า (เช่น - ไม่มีการทดสอบหรือ - ไม่มีตัวอย่างหรือ - ไม่มีการใช้ร่วมกัน) ดูgithub.com/pocoproject/poco/blob/develop/configure
Homer6

ขอบคุณสำหรับสิ่งนั้น. ฉันต้องการมันต่อไปเพราะฉันสนใจที่จะทำสิ่งที่ฉันต้องทำ และฉันทราบว่าพวกเขามีการแยก JSON ที่นั่นด้วยซึ่งดีเพราะฉันจะต้องทำอย่างนั้นหลังจากส่งคำขอ HTTP ซึ่งเป็นสิ่งที่ฉันได้รับจากห้องสมุด
CashCow

มันเป็นในขณะที่ผ่านมา แต่นี้เป็นเพียงการแจ้งให้คุณทราบไม่มีผู้เชื่อมโยงของคุณที่มีการทำงานในขณะนี้แม้ GitHub repo ดูเหมือนลบออก ...
Hack06

33

มีใหม่น้อยผู้ใหญ่ขดเสื้อคลุมได้รับการพัฒนาที่เรียกว่าC ++ จอง นี่คือคำขอ 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;
}

สนับสนุนคำกริยา HTTP และตัวเลือก curl ที่หลากหลาย มีเอกสารการใช้งานมากขึ้นเป็นที่นี่

ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้ดูแลห้องสมุดนี้


10
ฉันอยู่ที่ฟ้าผ่าของ CppCon 2015 เมื่อวานนี้ ทำได้ดีมาก - ทั้งการพูดคุยและห้องสมุด ฉันชอบปรัชญาการออกแบบ "Curl for people" โดยเฉพาะ
U007D

สวัสดีฉันเพิ่งเจอโพสต์นี้ที่นี่มองหาคำขอ C ++ HTTP ที่ง่ายกว่าวิธีธรรมดา อย่างไรก็ตามฉันไม่ได้มีประสบการณ์กับห้องสมุดจริงๆและฉันไม่รู้วิธีรวมสิ่งนี้ไว้ในโครงการ Visual C ++ ของฉัน มีคำอธิบายอะไรบ้างไหม? ฉันรู้สึกว่ามันไม่เฉพาะเจาะจงกับห้องสมุด แต่ฉันไม่รู้ว่าจะทำอย่างไรกับสิ่งที่ฉันมีต่อหน้าฉันในขณะนี้โดยทั่วไป
Sossenbinder

2
@Sossenbinder หากคุณสามารถทำความคุ้นเคยกับ CMake คุณสามารถสร้างไฟล์สร้าง Visual Studio สำหรับโครงการนี้โดยใช้สิ่งนั้น กำหนดค่า appveyorไฟล์มีตัวอย่างคร่าวๆของวิธีการที่จะบรรลุเป้าหมายนี้
huu

2
ดูดี แต่การสร้างเป็นนรกดังนั้น lib ของคุณจึงไร้ประโยชน์ฉันไม่สามารถพึ่งพาผู้จัดการแพ็คเกจ (ต้องการวิธีการเพิ่มความน่าเชื่อถือจากภายนอก) และต้องการ lib ที่ใช้งานได้โดยเร็วที่สุด ...
dev1223

นั่นเป็นวิธีที่คุณทำ เมื่อคุณเปรียบเทียบสิ่งนี้กับ 200 บรรทัดของคำตอบที่ถูกโหวตมากที่สุดอันดับที่สอง .......
v.oddou

17

นี่คือ wrapper น้อยที่สุดของฉันรอบ ๆ cURL เพื่อให้สามารถดึงเว็บเพจเป็นสตริงได้ สิ่งนี้มีประโยชน์เช่นสำหรับการทดสอบหน่วย มันเป็นพื้น wrapper RAII รอบรหัส C

ติดตั้ง "libcurl" บนเครื่องyum install libcurl libcurl-develหรือเทียบเท่า

ตัวอย่างการใช้งาน:

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

การใช้งานคลาส:

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

16

libCURLเป็นตัวเลือกที่ดีสำหรับคุณ บทช่วยสอนควรบอกคุณว่าคุณต้องการอะไรโดยเฉพาะอย่างยิ่งสำหรับมือจับที่ง่ายขึ้นอยู่กับสิ่งที่คุณต้องทำ แต่โดยทั่วไปคุณสามารถทำได้เพียงเพื่อดูที่มาของหน้า:

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

ฉันเชื่อว่านี่จะทำให้ผลการพิมพ์เป็น stdout หากคุณต้องการจัดการมันแทน - ซึ่งฉันถือว่าคุณ - คุณต้องตั้งค่า CURL_WRITEFUNCTION ทั้งหมดที่กล่าวถึงในบทช่วยสอนการเชื่อมโยงข้างต้น


16

ตามที่คุณต้องการแก้ปัญหา c ++ คุณสามารถใช้Qt มันมีคลาส QHttp ที่คุณสามารถใช้ได้

คุณสามารถตรวจสอบเอกสาร :

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

Qt ยังมีอีกมากที่คุณสามารถใช้ในแอป C ++ ทั่วไป


4
ฉันคิดว่า QHttp ถูกแทนที่ด้วย QNetworkAccessManager และคลาสที่เกี่ยวข้องใน Qt 4.6 และรุ่นที่ใหม่กว่า
juzzlin

3
QNetworkAccessManagerได้รับการบันทึกไว้ตั้งแต่ Qt 4.4; และใน Qt 4.8 พูดว่า: QHttp - This class is obsolete. It is provided to keep old source code working. We strongly advise against using it in new code.ดังนั้นฉันเดาว่ามันยังใช้ได้ถ้าคุณไม่สนใจคำเตือนที่เลิกใช้
Jesse Chisholm

13

คุณอาจต้องการตรวจสอบC ++ REST SDK (ชื่อรหัสว่า "Casablanca") http://msdn.microsoft.com/en-us/library/jj950081.aspx

ด้วย C ++ REST SDK คุณสามารถเชื่อมต่อกับเซิร์ฟเวอร์ HTTP ได้ง่ายขึ้นจากแอป C ++ ของคุณ

ตัวอย่างการใช้งาน:

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

C ++ REST SDK เป็นโครงการ Microsoft สำหรับการสื่อสารบนไคลเอนต์ - เซิร์ฟเวอร์บนคลาวด์ในรหัสเนทีฟโดยใช้การออกแบบ C ++ API แบบอะซิงโครนัสที่ทันสมัย


10

กับคำตอบนี้ฉันหมายถึงคำตอบจาก Software_Developer ด้วยการสร้างรหัสขึ้นใหม่ฉันพบว่าบางส่วนถูกคัดค้าน ( gethostbyname()) หรือไม่มีการจัดการข้อผิดพลาด (การสร้างซ็อกเก็ตส่งบางอย่าง) สำหรับการดำเนินการ

รหัส windowsต่อไปนี้ได้รับการทดสอบด้วย Visual Studio 2013 และ Windows 8.1 64 บิตเช่นเดียวกับ Windows 7 64 บิต มันจะกำหนดเป้าหมายการเชื่อมต่อ IPv4 TCP กับเว็บเซิร์ฟเวอร์ของ 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;
}

อ้างอิง:

การเลิกใช้งานของ gethostbyname

มูลค่าส่งคืนของซ็อกเก็ต ()

มูลค่าส่งคืนของการส่ง ()


7

C ++ ไม่มีวิธีการใด ๆ ที่จะทำโดยตรง มันขึ้นอยู่กับว่าคุณมีแพลตฟอร์มและห้องสมุดใด

ในกรณีที่เลวร้ายที่สุดคุณสามารถใช้ boost :: asio library เพื่อสร้างการเชื่อมต่อ TCP ส่ง HTTP header (RFC 2616) และแยกการตอบสนองโดยตรง ดูความต้องการของแอปพลิเคชันของคุณซึ่งง่ายพอที่จะทำ


1
มันทำ - อย่างน้อยตอนนี้ :) stackoverflow.com/a/51959694/1599699
แอนดรู

@Andrew: หาก"ทำ"ของคุณจะอยู่ที่"c ++"ของ sybreon ไม่ได้ให้วิธีการใด ๆ โดยตรง ดังนั้นคำตอบที่เชื่อมโยงนั้นไม่ถูกต้องเนื่องจากมันแสดงวิธีการทำโดยใช้ข้อมูลเฉพาะของระบบ
เซบาสเตียนมัค

@ เซบาสเตียนมาชฉันหมายความว่าอย่างไร เพียงนำเข้าไลบรารีที่ระบบจัดให้และเรียกใช้ฟังก์ชันและจะทำงานให้คุณ เปรียบเทียบกับตัวเลือก c ++ อื่น ๆ ทั้งหมดซึ่งอาจเป็นเรื่องยากหรือใช้รหัสบุคคลที่สาม ฉันคิดว่าสวยโดยตรง
แอนดรู

1
@Andrew: เป็น "ระบบที่ให้" เฉพาะใน Windows ในระบบอื่นมันแตกต่างกัน และมันไม่มีอะไรเกี่ยวข้องกับ "C ++ ไม่มีวิธีใด ๆ ที่จะทำโดยตรง" ซึ่งหมายถึง "มาตรฐาน C ++ ไม่ได้"
เซบาสเตียนมัค

@SebastianMach ใช่ แต่มันก็เป็นอัตนัยด้วยเช่นกันเพราะ c ++ ยังทำงานบนโทรศัพท์มือถือแท็บเล็ต microcontrollers เป็นต้นหากไม่ใช่ทุก ๆ อุปกรณ์หรือระบบปฏิบัติการที่รองรับการทำงานบางอย่างใน c ++ เราเรียกมันว่า c ++ โดยตรงไม่ใช่หรือ? OP ไม่ได้พูดว่า "c ++ standard" เขาแค่พูด c ++ คำตอบเหล่านี้ให้บริการโซลูชั่น Linux และ Windows เพราะโดยทั่วไปแล้วสิ่งที่คุณจะใช้สำหรับสิ่งนี้ ดังนั้นแน่นอนว่าไม่ใช่โซลูชัน Linux แต่ใช่มีให้โดยระบบปฏิบัติการหลักโดยตรง
แอนดรู

6

นี่คือรหัสบางส่วนที่จะทำงานโดยไม่จำเป็นต้องใช้ไลบรารี่ของบุคคลที่สาม: ก่อนอื่นให้กำหนดเกตเวย์ผู้ใช้รหัสผ่านและพารามิเตอร์อื่น ๆ ที่คุณต้องส่งไปยังเซิร์ฟเวอร์เฉพาะนี้ก่อน

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

นี่คือรหัสตัวเอง:

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

ที่ควรทำงานบนสภาพแวดล้อม Win32 API

นี่คือตัวอย่าง


ฉันควรใส่เกตเวย์อะไร ไม่มีเกตเวย์แช่ง ... Win API นั้นแย่มาก
Tomáš Zato - Reinstate Monica

1
"เกตเวย์" เป็นเพียงคำทั่วไปสำหรับ URI ( en.wikipedia.org/wiki/Uniform_Resource_Identifier ) ที่ให้บริการโดยผู้ให้บริการ สิ่งนี้ไม่เกี่ยวข้องกับ Windows
Michael Haephrati

อ่าขอบคุณ ฉันไม่เคยได้ยินการแสดงออกที่จะใช้สำหรับ URL ดังนั้นฉันจึงสับสน ขอบคุณสำหรับการชี้แจง
Tomáš Zato - Reinstate Monica

ตกลงฉันทดสอบโค้ดและตัวอย่างของคุณไม่ได้เพิ่มขึ้น InternetConnectส่งคืนค่า null เมื่อระบุ URL แบบเต็ม แต่ส่งคืนค่าที่ไม่เป็นค่าว่างเมื่อระบุชื่อโดเมนเท่านั้น ดังนั้นเมื่อใด / ฉันจะใช้ URL แบบเต็มเพื่อรับหน้าเว็บที่ฉันต้องการดาวน์โหลดหรือไม่
Tomáš Zato - Reinstate Monica

ใช้ InternetOpenUrl () แทน InternetConnect () ถ้าคุณต้องการใช้ url
Al Po

4

อัปเดตคำตอบสำหรับเดือนเมษายน 2020:

ฉันประสบความสำเร็จอย่างมากเมื่อเร็ว ๆ นี้ด้วยcpp-httplib (ทั้งในฐานะลูกค้าและเซิร์ฟเวอร์) เป็นผู้ใหญ่และประมาณ RPS เธรดเดียวอยู่ที่ประมาณ 6k

บนขอบเลือดออกมากขึ้นมีเฟรมเวิร์กที่มีแนวโน้มมากcpv-frameworkที่สามารถรับได้ประมาณ 180k RPS ในสองคอร์ (และจะปรับขนาดได้ดีกับจำนวนของคอร์เพราะมันขึ้นอยู่กับเฟรมseastarซึ่งให้พลังกับ DB ที่เร็วที่สุด ดาวเคราะห์scylladb )

อย่างไรก็ตาม cpv-framework ยังค่อนข้างไม่สมบูรณ์ ดังนั้นสำหรับการใช้งานส่วนใหญ่ฉันขอแนะนำ cpp-httplib

คำแนะนำนี้แทนที่คำตอบก่อนหน้าของฉัน (8 ปีที่แล้ว)


ขอบคุณจะลองในอนาคตอันใกล้นี้)
Hack06

ฉันชอบวิธี 1 ไฟล์ (5K-line ก็โอเค) ของ cpp-httplib คุณมีความคิดเกี่ยวกับประสิทธิภาพของมันหรือไม่?
Hack06

1
@ Hack06 เกณฑ์มาตรฐานคร่าวๆคือประมาณ 6,000 คำขอต่อวินาที (RPS)
Homer6

3

C และ C ++ ไม่มีไลบรารีมาตรฐานสำหรับ HTTP หรือแม้แต่การเชื่อมต่อซ็อกเก็ต ในช่วงหลายปีที่ผ่านมามีการพัฒนาห้องสมุดแบบพกพา ใช้กันอย่างแพร่หลายในขณะที่คนอื่น ๆ ได้กล่าวว่าเป็นlibcurl

นี่คือรายการทางเลือกของ libcurl (มาจากเว็บไซต์ของ libcurl)

นอกจากนี้สำหรับ Linux นี่เป็นไคลเอนต์ HTTP แบบง่าย คุณสามารถใช้ไคลเอนต์ HTTP GET อย่างง่ายของคุณเองได้ แต่สิ่งนี้จะไม่ทำงานหากมีการตรวจสอบสิทธิ์หรือการเปลี่ยนเส้นทางที่เกี่ยวข้องหรือหากคุณต้องการทำงานเบื้องหลังพร็อกซี สำหรับกรณีเหล่านี้คุณต้องมีไลบรารีแบบเต็มเช่น libcurl

สำหรับซอร์สโค้ดที่มี libcurl สิ่งนี้จะใกล้เคียงที่สุดกับสิ่งที่คุณต้องการ (Libcurl มีตัวอย่างมากมาย) ดูที่ฟังก์ชั่นหลัก เนื้อหา html จะถูกคัดลอกไปยังบัฟเฟอร์หลังจากการเชื่อมต่อสำเร็จ เพียงแทนที่ parseHtml ด้วยฟังก์ชันของคุณเอง


3

คุณสามารถใช้ไลบรารีEmbeddedRest มันเป็นไลบรารี่แบบหัวเท่านั้น ดังนั้นจึงเป็นเรื่องง่ายที่จะรวมไว้ในโครงการของคุณและไม่จำเป็นต้องมีการรวบรวมเพราะไม่มี.cppไฟล์อยู่ในนั้น

ขอตัวอย่างจากreadme.mdจาก 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;
}

ไม่คอมไพล์ใน Win32: /
uhfocuz

@uhfocuz lib ถูกเขียนขึ้นสำหรับ iOS และ Android แต่ฉันสามารถช่วยคุณคอมไพล์มันสำหรับ Win32 ไม่ยากเกินไป
fnc12

ฉันชอบความเบาของมันสำหรับการใช้งานของฉันมันรวบรวมได้ดีบน Mac ของฉัน แต่บน Windows libs นั้นแตกต่างจากที่คุณไม่มีnetdb.hฯลฯ ดังนั้นฉันจึงต้องการความช่วยเหลือใช่
uhfocuz

@uhfocuz สิ่งที่คุณต้องทำคือการเพิ่มเงื่อนไขเช่น#ifdef _WIN32และเพิ่มมีรหัสเฉพาะหน้าต่าง ดูที่นี่ - ไม่แตกต่างกันมากระหว่างซ็อกเก็ตยูนิกซ์และซ็อกเก็ตหน้าต่าง ฉันเห็นความแตกต่างที่สำคัญสองประการ: 1) โทรWSAStartupก่อนและ 2) ใช้closesocketแทนclose
fnc12

@uhfocuz โปรดสร้างปัญหาใน repo ของฉัน - ฉันจะเพิ่มการสนับสนุน win32 เมื่อฉันมีเวลาเพียงพอ
fnc12

3

โปรโตคอล HTTP นั้นง่ายมากดังนั้นจึงง่ายมากในการเขียนไคลเอ็นต์ HTTP นี่คือหนึ่ง

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

มันใช้ HTTP GET เพื่อดึงไฟล์จากเว็บเซิร์ฟเวอร์ทั้งเซิร์ฟเวอร์และไฟล์เป็นพารามิเตอร์บรรทัดคำสั่ง ไฟล์ระยะไกลจะถูกบันทึกลงในสำเนาในเครื่อง

ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียน

แก้ไข: URL ที่แก้ไข


URL ที่ระบุไม่ถูกต้อง
Shravan40 40

3

โปรดทราบว่าสิ่งนี้ไม่จำเป็นต้องใช้ libcurl, Windows.h หรือ WinSock! ไม่มีการรวบรวมไลบรารีไม่มีการกำหนดค่าโครงการ ฯลฯ ฉันมีรหัสนี้ทำงานใน Visual Studio 2017 c ++ บน 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();

ฉันเพิ่งรู้วิธีการทำเช่นนี้เพราะฉันต้องการสคริปต์การเข้าถึง API อย่างง่ายไลบรารีอย่าง libcurl ทำให้ฉันเกิดปัญหาทุกประเภท (แม้เมื่อฉันทำตามคำแนะนำ ... ) และ WinSock นั้นต่ำเกินไปและซับซ้อนเกินไป .

ฉันไม่แน่ใจเกี่ยวกับรหัสการอ่านของIStream ทั้งหมด (โดยเฉพาะอย่างยิ่งในขณะที่เงื่อนไข - รู้สึกฟรีเพื่อแก้ไข / ปรับปรุง) แต่เฮ้มันใช้งานได้ดีไม่ยุ่งยาก! (มันสมเหตุสมผลสำหรับฉันว่าตั้งแต่ฉันใช้การบล็อก (ซิงโครนัส) การโทรสิ่งนี้ดีซึ่งbytesReadจะเป็น> 0U จนกระทั่งกระแส ( ISequentialStream ?) อ่านเสร็จ แต่ใครจะรู้)

ดูเพิ่มเติม: URL Monikers และการอ้างอิงโพรโทคอลแบบเสียบได้แบบอะซิงโครนัส


มันถูกแก้ไขแล้ว แต่หลังจากมีประสบการณ์ใน c ++ มาพอสมควรแล้วฉันจะยืนตามคำกล่าวอ้างเดิมของฉันว่านี่อาจเป็นวิธีที่ง่ายที่สุดที่คุณจะสามารถทำสิ่งนี้ใน c ++ ... (ที่ อย่างน้อยตอนนี้ ... )
แอนดรู

ฉันเพิ่งทดสอบ URLOpenBlockingStream ด้วยบาง URL จากbadssl.com (ค่อนข้างดี) และการดำเนินการนี้จะล้มเหลวหากใบรับรอง SSL ไม่ถูกต้อง ในทุกกรณีที่ฉันทดสอบ (เพียงไม่กี่) เอาต์พุตของโค้ดด้านบนจะเป็นสตริงว่าง (ไม่มีข้อมูลสตรีม) นั่นเป็นสิ่งที่ดีงาม
แอนดรู

ฉันเห็นด้วยว่ามันคือ easiesst แต่คุณจะรับรหัสตอบกลับ http ได้อย่างไร
Robin

@ Robin Ha! คุณต้องการข้อความและรหัสการตอบสนองหรือไม่! คุณก็รู้เหมือนกันยกเว้นว่าบางทีถ้าคุณดูเอกสารประกอบแล้วดูในคู่มือ URL Monikers ที่คุณอาจพบคำตอบ ฉันดูเหมือนจะจำบางคนที่โพสต์รหัสออนไลน์ใช้ URLOpenBlockingStream ด้วยตนเองซึ่งจะช่วยให้การกำหนดค่าเพิ่มเติม แจ้งให้เราทราบหากคุณคิดอะไรออก!
แอนดรู

นอกจากนี้ยังมีสิ่งที่ฉันเพิ่งค้นพบ: docs.microsoft.com/en-us/windows/desktop/WinInet/ ......ไม่รู้ว่ามันดีไหม
แอนดรู

2

นี่คือรหัส C ++ 11 แบบง่าย ๆ ที่ใช้ libCURL เพื่อดาวน์โหลดเนื้อหาของ URL ลงใน a 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

โดยทั่วไปฉันแนะนำสิ่งข้ามแพลตฟอร์มเช่น cURL, POCO หรือ Qt อย่างไรก็ตามนี่คือตัวอย่างของ 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

หากคุณกำลังมองหาไลบรารีไคลเอนต์ HTTP ใน C ++ ที่รองรับหลายแพลตฟอร์ม (Linux, Windows และ Mac) เพื่อใช้บริการเว็บ Restful คุณสามารถมีตัวเลือกด้านล่าง

  1. QT Network Library - อนุญาตให้แอปพลิเคชันส่งคำขอเครือข่ายและรับการตอบกลับ
  2. C ++ REST SDK - ไลบรารี HTTP บุคคลที่สามที่เกิดขึ้นใหม่พร้อมการรองรับ PPL
  3. Libcurl - อาจเป็นหนึ่งใน lib http ที่ใช้มากที่สุดในโลกดั้งเดิม

1

แม้ว่าจะช้าไปหน่อย คุณอาจต้องการhttps://github.com/Taymindis/backcurl

จะช่วยให้คุณทำการโทร http บนการพัฒนามือถือ c ++ เหมาะสำหรับการพัฒนาเกมมือถือ

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

0

คุณสามารถใช้ ACE เพื่อทำ:

#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;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.