IT story

C ++로 HTTP 요청을 어떻게합니까?

hot-time 2020. 4. 12. 10:32
반응형

C ++로 HTTP 요청을 어떻게합니까?


C ++로 쉽게 HTTP 요청을 할 수있는 방법이 있습니까? 특히 페이지의 내용 (API)을 다운로드하고 내용이 1 또는 0을 포함하고 있는지 확인하고 싶습니다. 내용을 문자열로 다운로드 할 수도 있습니까?


나는 같은 문제가 있었다. libcurl 은 정말 완전합니다. C ++ 라이브러리를 요청할 때 관심을 가질 수 있는 C ++ 래퍼 curlpp 이 있습니다. neonWebDAV 를 지원하는 또 다른 흥미로운 C 라이브러리입니다 .

C ++를 사용하면 curlpp가 자연스럽게 보입니다. 소스 배포판에는 많은 예제가 제공됩니다. 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();

curlpp 소스 배포판examples디렉토리를 참조하십시오 . curlpp를 사용 하는 간단한 완전한 최소 디렉토리 뿐만 아니라 더 복잡한 경우가 많이 있습니다.

내 2 센트 ...


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

Linux에서는 cpp-netlib, libcurl, curlpp, urdl, boost :: asio를 시도하고 Qt를 고려했지만 라이센스에 따라 거절했습니다. 이것들은 모두 사용하기에 불완전하거나, 인터페이스가 느슨하거나, 문서가 열악하거나, 유지되지 않았거나 https를 지원하지 않았습니다.

그런 다음 https://stackoverflow.com/a/1012577/278976 의 제안에 따라 POCO를 시도했습니다. 와우, 나는 몇 년 전에 본 적이 있기를 바랍니다. HTTP GET 요청을 작성하는 예는 다음과 같습니다.

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

POCO는 무료이며 오픈 소스입니다 (부스트 라이센스). 그리고 아뇨, 저는 회사와 아무런 관련이 없습니다. 나는 그들의 인터페이스를 정말로 좋아한다. 훌륭한 직업들 (그리고 여자들).

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

이것이 누군가를 돕기를 바랍니다 ...이 라이브러리를 모두 시험해 보는 데 3 일이 걸렸습니다.


C ++ Requests 라는 덜 성숙 된 컬 래퍼가 개발되었습니다 . 간단한 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 동사 및 컬 옵션을 지원합니다. 더 많은 사용 설명서가 있습니다 .

면책 조항 : 나는이 도서관의 관리자입니다 .


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을 설정해야합니다. 이 모든 것은 위에 링크 된 curl 튜토리얼에서 다룹니다.


C ++ 솔루션을 원한다면 Qt를 사용할 수 있습니다 . 사용할 수있는 QHttp 클래스가 있습니다.

당신은 문서 를 확인할 수 있습니다 :

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

Qt는 또한 일반적인 C ++ 앱에서 사용할 수있는 많은 기능을 제공합니다.


다음은 웹 페이지를 문자열로 가져올 수 있도록 cURL을 둘러싼 최소 래퍼입니다. 예를 들어 단위 테스트에 유용합니다. 기본적으로 C 코드 주위의 RAII 래퍼입니다.

머신에 "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;
    }
};

C ++ REST SDK (코드 명 "Casablanca") 를 확인할 수 있습니다 . http://msdn.microsoft.com/en-us/library/jj950081.aspx

C ++ REST SDK를 사용하면 C ++ 앱에서 HTTP 서버에 더 쉽게 연결할 수 있습니다.

사용 예 :

#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는 최신 비동기 C ++ API 디자인을 사용하여 원시 코드로 클라우드 기반 클라이언트-서버 통신을위한 Microsoft 프로젝트입니다.


이 답변으로 저는 Software_Developer답변을 참조합니다 . 코드를 다시 작성하면 일부 부분이 더 이상 사용되지gethostbyname() 않거나 ( ) 작업에 대한 오류 처리 (소켓 생성, 전송)를 제공하지 않습니다 .

다음 Windows 코드 는 Visual Studio 2013 및 Windows 8.1 64 비트와 Windows 7 64 비트에서 테스트되었습니다. www.google.com 웹 서버와의 IPv4 TCP 연결을 대상으로합니다.

#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 사용 중단

socket ()의 반환 값

send ()의 반환 값


C ++은 직접 수행 할 수있는 방법을 제공하지 않습니다. 그것은 당신이 가진 플랫폼과 라이브러리에 전적으로 달려 있습니다.

최악의 경우 boost :: asio 라이브러리를 사용하여 TCP 연결을 설정하고 HTTP 헤더 (RFC 2616)를 보내고 응답을 직접 구문 분석 할 수 있습니다. 응용 프로그램 요구 사항을 살펴보면이 작업은 충분히 간단합니다.


C 및 C ++에는 HTTP 또는 소켓 연결을위한 표준 라이브러리가 없습니다. 수년 동안 일부 휴대용 라이브러리가 개발되었습니다. 다른 사람들이 말했듯이 가장 널리 사용되는 것은 libcurl 입니다.

다음은 libcurl의 대안 목록 입니다 (libcurl 웹 사이트에서 제공).

또한 Linux의 경우 이는 간단한 HTTP 클라이언트입니다. 간단한 HTTP GET 클라이언트를 직접 구현할 수 있지만 인증이나 리디렉션이 있거나 프록시 뒤에서 작업해야하는 경우에는 작동하지 않습니다. 이러한 경우 libcurl과 같은 본격적인 라이브러리가 필요합니다.

libcurl에와 소스 코드의 경우, 이것은 당신이 원하는에 가장 가까운 (libcurl에 많은있다 ). 주요 기능을보십시오. 성공적으로 연결되면 html 컨텐츠가 버퍼에 복사됩니다. parseHtml을 자신의 함수로 바꾸십시오.


embeddedRest 라이브러리 를 사용할 수 있습니다 . 가벼운 헤더 전용 라이브러리입니다. 따라서 프로젝트에 쉽게 포함시킬 수 있으며 .cpp파일 이없는 컴파일 원인이 필요하지 않습니다 .

readme.mdrepo 에서 요청 예 :

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

HTTP 프로토콜은 매우 간단하므로 HTTP 클라이언트를 작성하는 것은 매우 간단합니다. 여기 하나

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

HTTP GET을 사용하여 웹 서버에서 파일을 검색합니다. 서버와 파일은 모두 명령 행 매개 변수입니다. 원격 파일이 로컬 사본에 저장됩니다.

면책 조항 : 나는 저자입니다

수정 : 수정 된 URL


libcurl, Windows.h 또는 WinSock이 필요하지 않습니다. 라이브러리 컴파일, 프로젝트 구성 등이 없습니다.이 코드는 Windows 10의 Visual Studio 2017 c ++에서 작동합니다.

#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 읽기 코드 에 대해 잘 모르겠지만 (특히 while 조건-수정 / 개선 자유롭게 느끼십시오), 이봐, 그것은 작동 하고 번거 로움이 없습니다! (그것은, 내가 그에게 의미가 내가 사용하기 때문에 차단 (동기) 호출 이 그 괜찮 bytesRead항상 것> 0U 스트림까지 ( 대해 ISequentialStream는 ?) 완성 된 존재가 읽을 수 있습니다,하지만 누가 알 겠어.)

참조 : URL 모니 커와 비동기 플러그 프로토콜 참조


다음은 타사 라이브러리를 사용할 필요없이 작동하는 코드입니다. 먼저 게이트웨이, 사용자, 비밀번호 및이 특정 서버로 전송해야하는 기타 매개 변수를 정의하십시오.

#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 환경에서 작동합니다.

여기 예가 있습니다.


다음은 libCURL을 사용하여 URL의 내용을 다음으로 다운로드하는 간단한 C ++ 11 코드입니다 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);
}

일반적으로 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();

Restful 웹 서비스를 사용하기 위해 여러 플랫폼 (Linux, Windows 및 Mac)에서 지원되는 C ++에서 HTTP 클라이언트 라이브러리를 찾고있는 경우 아래 옵션을 가질 수 있습니다.

  1. QT 네트워크 라이브러리 -애플리케이션이 네트워크 요청을 보내고 응답을받을 수 있도록합니다.
  2. C ++ REST SDK -PPL을 지원하는 새로운 타사 HTTP 라이브러리
  3. Libcurl- 아마도 아마도 세계에서 가장 많이 사용되는 http lib 중 하나 일 것입니다.

조금 늦었지만. https://github.com/Taymindis/backcurl을 선호 할 수 있습니다 .

그것은 당신이 모바일 C ++ 개발에 http 호출을 할 수 있습니다. 모바일 게임 개발에 적합

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

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

참고 URL : https://stackoverflow.com/questions/1011339/how-do-you-make-a-http-request-with-c

반응형