1

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 ....

1 Answers1

2

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;
}
Gur Telem
  • 706
  • 1
  • 7
  • 14
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Tnks!!! actualy my problem is to verify each time if there is some things in the other side to download – Tarek Radah Sep 14 '16 at 00:44
  • it's okey for the loop and the error handling but I don't understand this : struct sHINTERNET {HINTERNET hInet; sHINTERNET(HINTERNET AInet = NULL) : hInet(AInet) {} ~sHINTERNET() { InternetCloseHandle(hInet); } operator HINTERNET() { return hInet; } bool operator!() const { return !hInet; } } – Tarek Radah Sep 14 '16 at 12:29
  • It is similar to a smart pointer (`std::auto_ptr`, `std::unique_ptr`, etc). It uses RAII to automate the calling of `InternetCloseHandle()`, thus allowing for cleaner and exception-safe code. If you are using C++11 or later, you can use `std::unique_ptr` instead of defining a custom struct. The end effect is the same. – Remy Lebeau Sep 14 '16 at 14:59