1

我正在尝试连接并确保我们设计的仪器提供的网络服务器上存在各种页面。我正在尝试使用 WinInet 命令通过 C++ Win32 执行此操作。

我很高兴我已通过 HTTP 正确连接到网络服务器:

hInternet = InternetOpen("Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0/*INTERNET_FLAG_ASYNC*/);
hhttp = InternetConnect(hInternet, "192.168.111.222", INTERNET_DEFAULT_HTTP_PORT, "admin", "admin", INTERNET_SERVICE_HTTP, 0, 0);

我相信我必须打开一个请求。

hHttpRequest = HttpOpenRequest(hhttp, "GET", "galogo.png", NULL, "192.168.111.222", lplpszAcceptTypes, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE, 0);

然后发送请求。

HttpSendRequest(hHttpRequest, NULL, 0, NULL, 0)

注:192.168.111.222是运行webserver的单位地址,galogo.png是首页显示的图片。另请注意,我在每个语句之间进行错误检查,因此如果我断开以太网连接,那么我确实会失败。

最初我确实尝试连接到 home.html 页面,但这总是通过,所以我想我应该尝试获取图像,但我可能缺乏知识。其他示例似乎随后会流式传输数据,但我不确定是否需要这样做。

我见过的大多数示例似乎都以这种格式显示 HtppSendRequest,我不太了解标头等。也许在这里我出错了。

4

3 回答 3

2

HttpQueryInfo 函数将提供与请求相关的标头信息,您可以从中提取 HTTP 状态代码。

您可以使用更高级别的 WinINet 函数更轻松地获得结果。我建议一个由 InternetOpen、InternetOpenUrl、HttpQueryInfo 组成的序列,然后如果 HTTP 状态代码正常,则重复调用 InternetReadFile。

这个 Delphi 代码(来自 Delphi 7,所以 pre-Unicode)似乎可以完成这项工作:-

function GetUrlContent(const Agent, Url: string): string;
var
  NetHandle: HINTERNET;
  UrlHandle: HINTERNET;
  Buffer: array [0..1024] of Char;
  BytesRead: DWORD;
  Dummy: DWORD;
  BufLen: DWORD;
  HttpStatus: string;
begin
  Result := '';
  NetHandle := InternetOpen(PChar(Agent), INTERNET_OPEN_TYPE_PRECONFIG,
    nil, nil, 0);

  if Assigned(NetHandle) then
  begin
    UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0,
      INTERNET_FLAG_RELOAD, 0);

    if Assigned(UrlHandle) then
    // UrlHandle valid?  Proceed with download.
    try
      BufLen := Length(Buffer);
      Dummy := 0;
      // only get the file if the HTTP status code is 200
      if HttpQueryInfo(UrlHandle, HTTP_QUERY_STATUS_CODE, @Buffer[0], BufLen, Dummy) then
      begin
        HttpStatus := Buffer;
        if HttpStatus = '200' then
        begin
          FillChar(Buffer, SizeOf(Buffer), 0);
          repeat
            Result := Result + Buffer;
            FillChar(Buffer, SizeOf(Buffer), 0);
            InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);
          until BytesRead = 0;
        end
        else begin
          raise Exception.CreateFmt('HTTP status code %s', [HttpStatus]);
        end;
      end
      else begin
        raise Exception.Create('Unable to read HTTP status code');
      end;
    finally
      InternetCloseHandle(UrlHandle);
    end
    else begin
      // UrlHandle is not valid.  Raise an exception.
      raise Exception.CreateFmt('Cannot open URL %s', [Url]);
    end;
    InternetCloseHandle(NetHandle);
  end
  else begin
    // NetHandle is not valid.  Raise an exception.
    raise Exception.Create('Unable to initialize WinINet');
  end;
end;
于 2012-11-26T15:43:52.703 回答
0

所以,结合使用 cURL 和 Wireshark,我终于成功了。我犯了一些根本性的错误,但基本上是在正确的轨道上。

首先打开连接,如前所述连接,确保它不是 ASYNC(这会导致一些重叠的 IO 错误):

hInternet = InternetOpen("Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0/*INTERNET_FLAG_ASYNC*/);

hhttp = InternetConnect(hInternet, "192.168.111.222", INTERNET_DEFAULT_HTTP_PORT, "admin", "admin", INTERNET_SERVICE_HTTP, 0, 0);

我需要创建请求然后发送它。我只需要指定页面,因为请求将包含连接详细信息。

hHttpRequest = HttpOpenRequest(hhttp, "GET", "home.html", NULL, NULL, lplpszAcceptTypes, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE, 0);

HttpSendRequest(hHttpRequest, NULL, 0, NULL, 0);

然后使用 HttpQueryInfo 函数检索状态并转换回整数。确保您从请求而不是连接发送句柄。

//These are defined earlier
DWORD statCharLen = 0;
char statChar[256]="";    
statCharLen = sizeof(statChar);

HttpQueryInfo(hHttpRequest, HTTP_QUERY_STATUS_CODE, statChar, &statCharLen, NULL);

最后关闭连接:

InternetCloseHandle(hInternet)

谢谢

于 2012-11-27T09:37:02.277 回答
0

其步骤很简单: 1- 打开连接 2- 连接 3- 打开请求 4- 发送请求 5- 读取文件 6- 保存文件(为 png 或 jpg) 7- 关闭句柄 代码如下:

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

using namespace std;
void download(string domain,string url,string filepath)
{
    //Step 1:
    HINTERNET hIntSession = InternetOpenA("MyApp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    //Step 2:
    HINTERNET hHttpSession = InternetConnectA(hIntSession, domain.c_str(), 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
    //Step 3:
    HINTERNET hHttpRequest = HttpOpenRequestA( hHttpSession, "GET",url.c_str(),0, 0, 0, INTERNET_FLAG_RELOAD, 0);
    TCHAR* szHeaders = L"";
    CHAR szReq[1024] = "";
    //Step 4:
    if( !HttpSendRequest(hHttpRequest, szHeaders, wcslen(szHeaders), szReq, strlen(szReq))) {
        DWORD dwErr = GetLastError();
        cout<<"error "<<dwErr<<endl;
        /// handle error
    }
    TCHAR szBuffer[1025];
    DWORD dwRead=0;
    FILE *f;
    f=fopen(filepath.c_str(),"wb");
    //Step 5 & 6:
    while(InternetReadFile(hHttpRequest,szBuffer, 1024, &dwRead) && dwRead)
    {
        fwrite(szBuffer,sizeof(BYTE),1024,f);
        dwRead=0;
    }
    fclose(f);
    //Step 7:
    InternetCloseHandle(hHttpRequest);
    InternetCloseHandle(hHttpSession);
    InternetCloseHandle(hIntSession);
}
int main()
{
    download("www.stacktoheap.com","images/stackoverflow.png","C:\\Example\\example.png");
}
于 2013-07-31T09:56:50.800 回答