C ++でHTTPリクエストを行うにはどうすればよいですか?


258

C ++でHTTPリクエストを簡単に作成する方法はありますか?具体的には、ページ(API)のコンテンツをダウンロードして、コンテンツに1または0が含まれているかどうかを確認します。コンテンツを文字列にダウンロードすることもできますか?


1
いいえ、現在、言語またはネットワーク用の標準ライブラリを介した組み込みのサポートはありません。ただし、ネットワーキングTS N4370があります。ライブラリの推奨事項を集めているため、この質問もVTCで受け付けました。

BoostBeastはどうですか?
twocrush

回答:


250

私も同じ問題を抱えていました。libcurlは本当に完全です。C ++ライブラリを要求するときに興味を引く C ++ラッパーcurlppがあります。neonは、WebDAVもサポートする興味深い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セント...


1
Macで最新バージョンが壊れているようです。ライブラリとしてリンクすると、config.hで問題が発生します。
eugene 2011

1
さて、上記をコンパイルできませんでした。ただし、と置き換えるos << myRequest.perform();myRequest.setOpt( new curlpp::options::WriteStream( &os ) ); myRequest.perform();結果が得られました。を使用しないでhttp://example.comください。空のページが返されます。より良い使用例http://www.wikipedia.org
Zane、

4
MSVSでcurlppをどのように構築しますか?私はそれを動作させることができません:(
mr5 '15

2
@ ryan-samによる最新の編集に同意しません。与えられたライブラリは「HTTPおよびWebDAV操作」のために明示的に作成されているため、Web開発ではなく「webdav」を書くことが作者の意図であったことは明らかです。
Bostrot 2018

2
@bostrot:そうだね。私は元に戻し、リンクを追加しました。人々は私がwebdevを書いたと思ったと思います。なんて残念です:)
ニューロ2018

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

Dev-C ++バージョン4.9.9.2でコンパイルするWindows Vistaでこのコードを試してみました。[Linker error] undefined reference to `WSAStartup @ 8 '
Expanding-Dev

4
@ Expanding-Dev MSVC(ビジュアルスタジオ)のみが「プラグマコメント」を理解します。他のものを使用する場合は、(他のライブラリと同様に)「ws2_32.lib」を手動でリンクする必要があります。
Navin、2014年

24
@JuanLuisSoldiこのコードの「美しさ」を評価するには、本当にWindows開発者である必要があると思います...
static_rtti 14

ここで(recvを使用して)何が受信されることになっていますか?出力として多くの意味不明なものを取得しています。また、なぜあなたは自分がしたことを送信バッファに入れましたか(例えばGET / HTTP/1.1.1/... etc)?送信するものをフォーマットする方法を見つけるにはどうすればよいですか?
LazerSharks 2014

43

アップデート2020:これに代わる新しい答えがあります。8年前の1つです。https//stackoverflow.com/a/61177330/278976

Linuxでは、cpp-netlib、libcurl、curlpp、urdl、boost :: asioを試してQtを検討しました(ただし、ライセンスに基づいて拒否しました)。これらはすべて、この使用に関して不完全であったか、不適切なインターフェイスがあったか、ドキュメントが不十分だったか、メンテナンスされていないか、httpsをサポートしていませんでした。

次に、https: //stackoverflow.com/a/1012577/278976の提案でPOCOを試しました。うわー、私はこの数年前に見たかったです。POCOでHTTP GETリクエストを行う例を次に示します。

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

POCOは無料のオープンソース(ブーストライセンス)です。いいえ、私はその会社とは何の関係もありません。私は本当に彼らのインターフェースが好きです。素晴らしい仕事の男(そしてギャル)。

https://pocoproject.org/download.html

これが誰かの役に立つことを願っています...これらのライブラリをすべて試すのに3日かかりました。


1
ここでは、追加の例を示します。github.com/pocoproject/poco/blob/develop/Net/samples/httpget/...
Homer6

2
私はあなたの提案でPocoをダウンロードしました。私はSTLに基づいて構築し、その多くを書き換えるよりもブーストするライトを好みます。さらに、私はCppUnitのファンではなく、特にビルドで実行されるテストが嫌いで、ビルド時にライブラリをテストする必要はありません。
CashCow 2014

少し大きいです。ただし、configure(つまり、-no-testsまたは--no-samplesまたは--no-sharedlibs)を使用して、テストおよびサンプル(または共有ライブラリ)のビルドを無効にすることができます。github.com/pocoproject/poco/blob/develop/configureを
Homer6

有難うございます。とにかく、必要なタスクを実行することに関心があるので、それが欲しいです。また、JSON解析も含まれていることに注意してください。これは、ライブラリを取得するためのHTTPリクエストを送信した後で実行する必要があるためです。
CashCow 14

少し前のことですが、これは、リンクが機能していないことを
通知する

33

C ++リクエストと呼ばれる、開発された新しい成熟度の低いcurlラッパーがあります。簡単な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リクエストを探しています。ただし、私はライブラリの経験があまりなく、ビジュアルスタジオのC ++プロジェクトにこれを含める方法がわかりません。どこかに説明はありますか?それは図書館に固有のものではないように感じますが、私は一般的に私の目の前にあるものをどう処理すればいいのか本当にわかりません。
Sossenbinder 2016年

2
@ Sossenbinder、CMakeに慣れることができれば、それを使用してこのプロジェクトのVisual Studioビルドファイルを生成できます。appveyorコンフィギュレーション・ファイルには、これを実現する方法のラフな例が含まれています。
ハウ2016

2
見栄えはいいが、ビルドは地獄なので、libは役に立たず、パッケージマネージャーに頼ることはできず(depを外部から追加するための信頼できる方法が必要)、できるだけ早く機能的なlibが必要になる...
dev1223

それがあなたのやり方です。これを2番目に多く投票された回答の200行と比較すると.......
v.oddou

17

文字列としてWebページを取得するだけのcURLの最小のラッパーを次に示します。これは、たとえば単体テストに役立ちます。基本的には、CコードのRAIIラッパーです。

マシンyum install libcurl libcurl-develまたは同等のものに「libcurl」をインストールします。

使用例:

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を設定する必要があります。これらはすべて、上記のリンクされたcurlチュートリアルで説明されています。


16

C ++ソリューションが必要な場合は、Qtを使用できます。使用できるQHttpクラスがあります。

あなたはドキュメントをチェックすることができます:

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

Qtには、一般的なC ++アプリで使用できる多くの機能があります。


4
QHttpは、Qt 4.6以降のバージョンでQNetworkAccessManagerおよび関連クラスに置き換えられたと思います。
juzzlin 2015年

3
QNetworkAccessManagerQt 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.廃止予定の警告を無視すれば、まだ利用できると思います。
ジェシーチザム2015

13

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プロジェクトです。


10

この回答では、Software_Developerからの回答を参照しています。コードを再構築すると、一部のパーツが非推奨になっているgethostbyname())か、エラー処理を提供していない、操作の(ソケットの作成、何かの送信)が。

次のWindowsコードは、Visual Studio 2013およびWindows 8.1 64ビットとWindows 7 64ビットでテストされています。www.google.comのWebサーバーとの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()の戻り値


7

C ++には、それを直接行う方法はありません。それはあなたが持っているプラ​​ットフォームとライブラリに完全に依存します。

最悪の場合、boost :: asioライブラリを使用してTCP接続を確立し、HTTPヘッダー(RFC 2616)を送信して、応答を直接解析できます。アプリケーションのニーズを見ると、これは十分に簡単です。


1
それは、少なくとも今はそうです。:) stackoverflow.com/a/51959694/1599699
Andrew

@Andrew:あなたの「それがする」がsybreonの「C ++が直接それを行う方法を提供していない」に対処する場合。、リンクされた回答は、システムの詳細を使用して行う方法を示しているため無効です。
セバスチャンマッハ

@SebastianMachつまり、そうです。システムが提供するライブラリーをインポートして関数を呼び出すだけで、ジョブが実行されます。それを他のすべてのc ++オプションと比較すると、それは本当に難しいか、サードパーティのコードを使用しています。それはかなり直接的だと思います。
Andrew

1
@Andrew:Windowsでのみ「システム提供」です。他のシステムでは異なります。また、「C ++は直接実行する方法を提供していません」とは何の関係もありません。つまり、「C ++標準にはありません」という意味です。
セバスチャンマッハ

@SebastianMachええ、でも主観的です。c++は携帯電話のタブレットマイクロコントローラーなどでも動作するためです。すべてのデバイスまたはOSがc ++の一部の機能を簡単にサポートしているわけではない場合、c ++から直接提供されていないものと呼びますか?OPは「c ++標準」とは言いませんでした。彼はc ++とだけ言いました。これらの答えはLinuxとWindowsのソリューションを提供しています。これは通常、このような場合に使用するものだからです。確かに、それはLinuxソリューションではありませんが、そうです、そうです、それは主要なOSから直接提供されています。
Andrew

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はとても悪いです。
トマーシュザト-モニカを復活させる

1
「ゲートウェイ」は、サービスプロバイダーによって提供されるURI(en.wikipedia.org/wiki/Uniform_Resource_Identifier)の単なる一般的な単語です。これはWindowsとは関係ありません。
Michael Haephrati

ああ、ありがとう。その表現がURLに使われるのを聞いたことがないので、ちょっと混乱しました。説明をありがとう。
トマーシュザト-モニカを復活させる

さて、私はコードをテストしましたが、あなたの例は追加されません。InternetConnect完全なURLが指定された場合はnullを返しますが、ドメイン名のみが指定された場合はnull以外の値を返します。それで、いつ/どこで完全なURLを使用して、ダウンロードしたいページを取得しますか?
トマーシュザト-モニカを復活させる

URLを使用する場合は、InternetConnect()ではなくInternetOpenUrl()を使用してください
Al Po

4

2020年4月の回答の更新:

最近、cpp-httplibで多くの成功を収めました(クライアントとサーバーの両方)で。成熟しており、おおよそのシングルスレッドRPSは約6kです。

さらに最先端に、本当に有望なフレームワーク、cpv-frameworkがあります。 2つのコアで約 RPSを実現できるがあります(これは、最高速のDBを駆動するseastarフレームワークに基づいているため、コアの数にれます)惑星scylladb)。

ただし、cpv-frameworkはまだ比較的未成熟です。したがって、ほとんどの用途では、cpp-httplibを強くお勧めします。

この推奨事項は、以前の回答(8年前)に代わるものです。


ありがとう、多分近いうちに試してみます;)
Hack06

私はcpp-httplibの1ファイル(5K行で問題ありません)アプローチが本当に好きです。そのパフォーマンスについてのアイデアはありますか?
Hack06

1
@ Hack06大まかなベンチマークは、1秒あたり約6000リクエスト(RPS)でした。
Homer6

3

CおよびC ++には、HTTPまたはソケット接続用の標準ライブラリがありません。長年にわたって、いくつかのポータブルライブラリが開発されてきました。他の人が言っているように、最も広く使用されているのはlibcurlです。です。

こちらがリストですlibcurlの代替のを(libcurlのWebサイトから取得)。

また、Linuxの場合、これはは単純なHTTPクライアントです。独自の単純なHTTP GETクライアントを実装することもできますが、認証またはリダイレクトが関係している場合、またはプロキシの背後で作業する必要がある場合は、これは機能しません。これらの場合には、libcurlのような本格的なライブラリが必要です。

libcurlを使用したソースコードの場合、これは必要なものに最も近いものです(Libcurlには多くのがあります)。メイン関数を見てください。接続が成功すると、htmlコンテンツがバッファにコピーされます。parseHtmlを独自の関数に置き換えるだけです。


3

embeddedRestライブラリを使用できます。軽量なヘッダーのみのライブラリです。したがって、プロジェクトに簡単に組み込むことができ、.cppファイルをコンパイルする必要がないため、コンパイルする必要がありません。

readme.mdリポジトリからのリクエスト例:

#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ではnetdb.h
lib

@uhfocuzする必要があるのは、条件#ifdef _WIN32を追加してそこにウィンドウ固有のコードを追加することだけです。ここを見てください-UNIXソケットとWindowsソケットの間に大きな違いはありません。2つの主な違いがあります。1)WSAStartup最初に電話する、2)closesocket代わりに使用するclose
fnc12

@uhfocuzリポジトリに問題を作成してください-十分な時間があれば、win32サポートを追加します
fnc12

3

HTTPプロトコルは非常に単純なので、HTTPクライアントを作成するのも非常に簡単です。ここにある

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

HTTP GETを使用してWebサーバーからファイルを取得します。サーバーとファイルはどちらもコマンドラインパラメーターです。リモートファイルはローカルコピーに保存されます。

免責事項:私は作者です

編集:編集されたURL


指定されたURLは無効です。
Shravan40

3

これは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ストリーム(ISequentialStream?)の読み取りが完了するまで、常に0Uを超えますが、誰が知っているのでしょうか。)

参照:URLモニカーおよび非同期プラグ可能なプロトコルリファレンス


それは編集されましたが、c ++でのかなりの経験の後、これはおそらく c ++でこの種のことを行うことができる最も簡単な方法であるという私の元の主張を支持します...(At少なくとも今のところ...)
Andrew

私はたまたまbadssl.comからのいくつかのURLでURLOpenBlockingStreamをテストしました(かなり便利です)。SSL証明書が悪い場合、この操作は失敗します。私がテストしたすべてのケース(ほんの数例)では、上記のコードの出力は空の文字列になります(ストリームデータなし)。とてもいいですね。
アンドリュー

私はそれが最も簡単だと思いますが、どのようにhttp応答コードを取得しますか?
ロビン

@ロビンハ!メッセージ応答コードが必要ですか?あなたも私と同じように知っていますが、ドキュメントを見て、より手動のURL Monikersのものを見ると、答えが見つかるかもしれません。URLOpenBlockingStreamを手動で実装するコードをオンラインで投稿した人を思い出したようです。これにより、より多くの構成が可能になります。何かわかったら教えてください!
アンドリュー

私が見つけたばかりのこれもあります:docs.microsoft.com/en-us/windows/desktop/WinInet/…それが良いかどうかわからない。
アンドリュー

2

以下は、(比較的)単純なC ++ 11コードで、libCURLを使用してURLのコンテンツを 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

Restful Webサービスを利用するために複数のプラットフォーム(Linux、Windows、Mac)でサポートされているC ++のHTTPクライアントライブラリを探している場合。以下のオプションがあります。

  1. QTネットワークライブラリ -アプリケーションがネットワーク要求を送信し、応答を受信できるようにします
  2. C ++ REST SDK -PPLをサポートする新しいサードパーティHTTPライブラリ
  3. Libcurl-おそらく、ネイティブの世界で最も使用されているhttp libの1つです。

1

少し遅れますが。あなたは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

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.