0

我正在尝试在 C++ 中使用 WinHTTP 获取网页的内容。它有点工作,除了我能够查看部分源而不是整个源。

OpenSSL 的东西在那里,因为最终我希望能够通过 SSL 进行 HTTP,但这是下一个挑战。

#include <windows.h>
#include <Wininet.h>

#pragma comment(lib, "Crypt32.lib")
#pragma comment(lib, "wininet.lib")


bool SetupSSL(HINTERNET request)
{
    HCERTSTORE store = CertOpenSystemStore(NULL,"CA");
    DWORD ret = 0;
    bool ok = false;

    if(store==NULL)     
        return false;
    PCCERT_CONTEXT context = CertFindCertificateInStore(store,X509_ASN_ENCODING,0,CERT_FIND_SUBJECT_STR,L"WebClient",NULL);
    if(context!=NULL)
    {            
        ok = InternetSetOption(request,INTERNET_OPTION_CLIENT_CERT_CONTEXT,(LPVOID)context,sizeof(CERT_CONTEXT))==TRUE;
        if(!ok)         
            ret = GetLastError();  
        CertFreeCertificateContext(context);
    }
    MessageBoxA(0, "1", 0, 0);
    CertCloseStore(store,0);
    return ok;
};


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{   
    HINTERNET hint = InternetOpen("WebTestClient",INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0);
    if(hint!=NULL)
    {
        //InternetSetStatusCallback(hint,&HTTPStatusCallbackFunc);
        HINTERNET hsession = InternetConnect(hint,"encrypted.google.com",443,NULL,NULL,3,0,NULL);

        if(hsession!=NULL)
        {
            HINTERNET hreqest = HttpOpenRequest(hsession,"GET","/","HTTP/1.1",NULL,NULL,INTERNET_FLAG_SECURE|INTERNET_FLAG_NO_AUTH,NULL);
            if(hreqest!=NULL)
            {
                //if(SetupSSL(hreqest))
                //{ 

                    if(HttpSendRequest(hreqest,NULL,0, NULL, 0))
                    {                   
                        //char szResponse[1024] = "";
                        char szBuffer[1024] = "";
                        DWORD dwRead=0;                 


                        while(InternetReadFile(hreqest, szBuffer, sizeof(szBuffer)-1, &dwRead) && dwRead) 
                        {
                            //strcat(szBuffer, szResponse);
                            szBuffer[dwRead] = 0;
                            OutputDebugStringA(szBuffer);               
                            dwRead=0;                       
                        }                                       

                        //InternetReadFile(hreqest, szBuffer, sizeof(szBuffer)-1, &dwRead);
                        MessageBoxA(0, szBuffer, 0, 0); // Only shows the first part of the source.
                    }               

                //}
                //else
                //{
                    //MessageBoxA(0, "SetupSSL failed", 0, 0);
                //}
                InternetCloseHandle(hreqest);
            }       
            InternetCloseHandle(hsession);
        }       
        InternetCloseHandle(hint);
    }

    return 0;
}

OutPutDebugStringA 正在将整个源输出到调试控制台,因此一切就绪。只是不将其全部存储在 szBuffer 变量中。我认为这可能与循环有关。

4

1 回答 1

1

while(InternetReadFile(hreqest, szBuffer, sizeof(szBuffer)-1, ...

你继续阅读使用InternetReadFile到同一个缓冲区szBuffer覆盖你已经在那里的东西。

通常,您需要一个灵活/重新分配的缓冲区,或缓冲区列表,为了代码简洁,您可以执行以下操作来顺序读取足够大的固定大小缓冲区:

static const SIZE_T g_nBufferCapacity = 128 * 1024; // 128 KB
CHAR szBuffer[nBufferCapacity] = "";
SIZE_T nBufferSize = 0;

szBuffer[0] = 0;
for(; ; )
{
  DWORD nReadableSize = min(1024, sizeof(szBuffer) - nBufferSize - 1);
  DWORD nReadSize = 0;
  InternetReadFile(hreqest, szBuffer + nBufferSize, nReadableSize, &nReadSize); // TODO: Error Checking
  if(!nReadSize)
    break;
  szBuffer[nBufferSize + nReadSize] = 0;
  OutputDebugStringA(szBuffer + nBufferSize);               
  nBufferSize += nReadSize;
}                                       
于 2013-08-16T17:13:20.983 回答