Search code examples
c++httpwinapiwininetwinhttp

WinInet : How to send multiple http get request with C++


I'm trying to write a program that download some things from a remote server,

#include <iostream>
#include <string>
#include <Windows.h>
#include <WinInet.h>
#pragma comment(lib,"wininet.lib")

using namespace std;

string Get(){
    DWORD size = 0;
    DWORD wrt;
    string msg = "";
    HINTERNET io=InternetOpen("Downloader",INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0);
    HINTERNET ic=InternetConnect(io,"192.168.1.15",8080,NULL,NULL,INTERNET_SERVICE_HTTP,0,0);
    HINTERNET hreq=HttpOpenRequest(ic,NULL,"/cgi-bin/cmd.py","HTTP/1.0",NULL,NULL,0,0);
    HttpSendRequest(hreq,NULL,0,NULL,0);
    InternetQueryDataAvailable(hreq,&size,0,0);
    char* buffer = new char[size+1];
    memset(buffer,0,size+1);
    InternetReadFile(hreq,buffer,size,&wrt);
    msg += buffer;
    free(buffer);
    InternetCloseHandle(io);
    InternetCloseHandle(ic);
    InternetCloseHandle(hreq);
    return msg;
}


int main(){
    while(TRUE){
        string msg=Get();
        if(msg.length()>1){
            cout<<msg<<endl;
        }
        Sleep(2000);
    }
return 0;
}

In the other side (on server ) I run a python CGI script , to send the text. The problem is that the program send the GET request just one time, even if there is a loop and the msg.length() is equal to 0 , in the other side I can see that I just recieved one GET request . Can someone solve my problem, or any idea ....


Solution

  • You need to add error handling to each WinInet API call.

    You also need to loop InternetReadFile(), as it may take multiple reads to receive the full response. And you need to take into account the number of bytes actually read when appending each buffer to your std::string.

    Try something more like this:

    #include <iostream>
    #include <string>
    #include <sstream>
    #include <stdexcept>
    
    #pragma comment(lib, "wininet.lib")
    
    struct sHINTERNET
    {
        HINTERNET hInet;
    
        sHINTERNET(HINTERNET AInet = NULL) : hInet(AInet) {}
        ~sHINTERNET() { InternetCloseHandle(hInet); }
    
        operator HINTERNET() { return hInet; }
        bool operator!() const { return !hInet; }
    }
    
    void WinInetError(const char *FuncName)
    {
        DWORD dwErr = GetLastError();
    
        std::ostringstream oss;
        oss << FuncName << " failed!";
    
        if (dwErr != ERROR_INTERNET_EXTENDED_ERROR)
            oss << " Error: " << dwErr;
        else
        {
            DWORD dwLen = 0;
            InternetGetLastResponseInfo(&dwErr, NULL, &dwLen);
    
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
            {
                std::basic_string<TCHAR> msg;
    
                ++dwLen;
                msg.resize(dwLen);
    
                if (InternetGetLastResponseInfo(&dwErr, &msg[0], &dwLen))
                {
                    msg.resize(dwLen);
                    oss << " Error: " << msg;
                }
            }
        }
    
        throw std::runtime_error(oss.str());
    }
    
    std::string Download()
    {
        sHINTERNET io = InternetOpen("Downloader", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
        if (!io)
            WinInetError("InternetOpen");
    
        sHINTERNET ic = InternetConnect(io, "192.168.1.15", 8080, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
        if (!ic)
            WinInetError("InternetConnect");
    
        sHINTERNET hreq = HttpOpenRequest(ic, NULL, "/cgi-bin/cmd.py", "HTTP/1.0", NULL, NULL, 0, 0);
        if (!hreq)
            WinInetError("HttpOpenRequest");
    
        if (!HttpSendRequest(hreq, NULL, 0, NULL, 0))
            WinInetError("HttpSendRequest");
    
        std::string data;
        char buffer[1024];
        DWORD wrt;
    
        do
        {
            if (!InternetReadFile(hreq, buffer, sizeof(buffer), &wrt))
                WinInetError("InternetReadFile");
    
            if (wrt == 0)
                break; 
    
            data.append(buffer, wrt);
        }
        while (true);
    
        return data;
    }
    
    int main()
    {
        while (true)
        {
            try
            {
                std::string data = Download();
                std::cout << data << std::endl;
            }
            catch (const std::exception &e)
            {
                std::cerr << "Error! " << e.what() << std::endl;
            }
    
            Sleep(2000);
        }
    
        return 0;
    }