How do you make a HTTP request with C++?

后端 未结 22 2503
有刺的猬
有刺的猬 2020-11-22 06:25

Is there any way to easily make a HTTP request with C++? Specifically, I want to download the contents of a page (an API) and check the contents to see if it contains a 1 o

相关标签:
22条回答
  • 2020-11-22 06:49

    With this answer I refer to the answer from Software_Developer. By rebuilding the code I found that some parts are deprecated (gethostbyname()) or do not provide error handling (creation of sockets, sending something) for an operation.

    The following windows code is tested with Visual Studio 2013 and Windows 8.1 64-bit as well as Windows 7 64-bit. It will target an IPv4 TCP Connection with the Web Server of 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;
    }
    

    References:

    Deprecation of gethostbyname

    Return Value of socket()

    Return Value of send()

    0 讨论(0)
  • 2020-11-22 06:51

    As you want a C++ solution, you could use Qt. It has a QHttp class you can use.

    You can check the docs:

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

    Qt also has a lot more to it that you could use in a common C++ app.

    0 讨论(0)
  • 2020-11-22 06:53

    The HTTP protocol is very simple, so it is very simple to write a HTTP client. Here is one

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

    It uses HTTP GET to retrieve a file from a web server, both server and file are command line parameters. The remote file is saved to a local copy.

    Disclaimer: I am the author

    check http.cc https://github.com/pedro-vicente/lib_netsockets/blob/master/src/http.cc

    int http_client_t::get(const char *path_remote_file)
    {
      char buf_request[1024];
    
      //construct request message using class input parameters
      sprintf(buf_request, "GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", path_remote_file, m_server_ip.c_str());
    
      //send request, using built in tcp_client_t socket
      if (this->write_all(buf_request, (int)strlen(buf_request)) < 0)
      {
        return -1;
      }
    

    EDIT: edited URL

    0 讨论(0)
  • 2020-11-22 06:54

    You may want to check C++ REST SDK (codename "Casablanca"). http://msdn.microsoft.com/en-us/library/jj950081.aspx

    With the C++ REST SDK, you can more easily connect to HTTP servers from your C++ app.

    Usage example:

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

    The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design.

    0 讨论(0)
  • 2020-11-22 06:58

    Generally I'd recommend something cross-platform like cURL, POCO, or Qt. However, here is a Windows example!:

    #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();
    
    0 讨论(0)
  • 2020-11-22 06:58

    CppRest SDK by MS is what I just found and after about 1/2 hour had my first simple web service call working. Compared that to others mentioned here where I was not able to get anything even installed after hours of looking, I'd say it is pretty impressive

    https://github.com/microsoft/cpprestsdk

    Scroll down and click on Documentation, then click on Getting Started Tutorial and you will have a simple app running in no time.

    0 讨论(0)
提交回复
热议问题