在VC中WININET使用HTTP的POSTA和GET方法

原文:http://blog.csdn.net/zeng622peng/article/details/5969059

Post资料:

SUMMARY

To properly simulate a Form submission using WinInet, you need to send a header that indicates the proper Content-Type. For Forms, the proper Content-Type header is: Content-Type: application/x-www-form-urlencoded

                 

MORE INFORMATION

     In many cases, the server does not respond appropriately if a Content-Type is not specified. For example, the Active Server Pages component of IIS 3.0 actually checks this header specifically for 'application/x-www-form- urlencoded' before adding form variables to the "Request.Form" object. This MIME/Content-Type indicates that the data of the request is a list of URL- encoded form variables. URL-encoding means that space character (ASCII 32) is encoded as ' ', special character such '!' encoded in hexadecemal form as '!'.

Here is a snippet of code that uses the MFC WinInet classes to simulate a Form POST request:

CString strHeaders = _T("Content-Type: application/x-www-form-urlencoded");

// URL-encoded form variables -

// name = "John Doe", userid = "hithere", other = "P&Q"

CString strFormData = _T("name=John Doe&userid=hithere&other=P&Q");

CInternetSession session;

CHttpConnection* pConnection = session.GetHttpConnection(_T("ServerNameHere"));

CHttpFile* pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,_T("FormActionHere"));

BOOL result = pFile->SendRequest(strHeaders,(LPVOID)(LPCTSTR)strFormData, strFormData.GetLength());

Without MFC, the same code translates to straight SDK calls as follows:

static

TCHAR hdrs[] = _T("Content-Type: application/x-www-form-urlencoded");

static

TCHAR frmdata[] = _T("name=John Doe&userid=hithere&other=P&Q");

statuc TCHAR accept[] = _T("Accept: */*");

    

// for clarity, error-checking has been removed

HINTERNET hSession = InternetOpen("MyAgent",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);

HINTERNET hConnect = InternetConnect(hSession, _T("ServerNameHere"),

                                     INTERNET_DEFAULT_HTTP_PORT,

                                     NULL,

                                     NULL,

                                     INTERNET_SERVICE_HTTP,

                                     0,

                                     1);

HINTERNET hRequest = HttpOpenRequest(hConnect,

                                     "POST",

                                     _T("FormActionHere"),

                                     NULL,

                                     NULL,

                                     accept,

                                     0,

                                     1);

HttpSendRequest(hRequest,

                hdrs,

                strlen(hdrs),

                frmdata,

                strlen(frmdata));

// close any valid internet-handles

我这里有一段程序,用来在一个对话框里显示出一次http     request的原始信息,不过使用Inet     API做的,希望能有帮助。   

void CHTTPRequestDlg::OnButtonRequest()

{

    UpdateData(TRUE);   

    HINTERNET hInternet = InternetOpen("Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)",

                                        INTERNET_OPEN_TYPE_DIRECT,

                                        NULL,

                                        NULL,

                                        NULL);   

    HINTERNET hSession = InternetConnect(hInternet,

                                        m_strHost,   

                                        m_nPort,

                                        "username",

                                        "password",   

                                        INTERNET_SERVICE_HTTP,

                                        0,

                                        0);   

    char* szAccept[] = {"*/*",NULL};

    CString strVerb;

    m_comboVerb.GetWindowText(strVerb);   

    HINTERNET hRequest = HttpOpenRequest(hSession,

                                        strVerb,

                                        m_strObject,

                                        NULL,

                                        NULL,

                                        (LPCSTR*)szAccept,

                                        0,

                                        0);   

    struct   

    {   

        char* Language;   

        char* Encoding;   

        char* ContentType;   

    }Headers = {"Accept-Language:zh-cn/r/n",

                "Accept-Encoding:gzip,deflate/r/n",   

                "Content-Type:application/x-www-form-urlencoded/r/n"};

    

    if(m_bLanguage)   

    {

        HttpAddRequestHeaders(hRequest,

                                Headers.Language,

                                -1,

                                HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);   

    }

    if(m_bEncoding)   

    {

        HttpAddRequestHeaders(hRequest,

                                Headers.Encoding,

                                -1,

                                HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);   

    }

    if(m_bContentType)   

    {

        HttpAddRequestHeaders(hRequest,

                                Headers.ContentType,

                                -1,

                                HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);   

    }

    LPCSTR lpAddHeader = NULL;

    LPCSTR lpContent = NULL;   

    if(m_strHeaders.GetLength())   

    {   

        if(m_strHeaders.Right(2) != "/r/n")   

        {

            m_strHeaders+="/r/n";   

        }

        lpAddHeader = (LPCSTR)m_strHeaders;   

    }   

    if(m_strContent.GetLength() && (strVerb == "POST" || strVerb == "PUT"))   

    {

        lpContent = (LPCSTR)m_strContent;   

    }

    HttpSendRequest(hRequest,

                    lpAddHeader,

                    -1,

                    (LPVOID)lpContent,

                    m_strContent.GetLength());   

    

    m_editContentGot.SetSel(0,-1);   

    m_editContentGot.ReplaceSel("");   

    

    LPSTR lpszData;        //buffer for the data   

    DWORD dwSize;        //size of the data available   

    DWORD dwDownloaded; //size of the downloaded data   

    

    //Set the cursor to an hourglass.   

    SetCursor(LoadCursor(NULL,IDC_WAIT));   

    

    // This loop handles reading the data.   

    while(1)   

    {   

        // The call to InternetQueryDataAvailable determines the amount of

        // data available to download.   

        if (!InternetQueryDataAvailable(hRequest,&dwSize,0,0))   

        {   

            SetCursor(LoadCursor(NULL,IDC_ARROW));   

            break;   

        }   

        else   

        {     

            // Allocates a buffer of the size returned by InternetQueryDataAvailable   

            lpszData = new char[dwSize+1];   

            

            // Reads the data from the HINTERNET handle.   

            if(!InternetReadFile(hRequest,(LPVOID)lpszData,dwSize,&dwDownloaded))   

            {   

                delete[] lpszData;   

                break;   

            }   

            else   

            {   

                // Adds a null terminator to the end of the data buffer   

                lpszData[dwDownloaded]='/0';   

                

                int nLen = m_editContentGot.GetWindowTextLength();   

                m_editContentGot.SetSel(nLen-1, nLen-1);   

                m_editContentGot.ReplaceSel(lpszData);   

                

                // Delete the two buffers   

                delete[] lpszData;   

                

                // Check the size of the remaining data.   If it is zero, break.   

                if (dwDownloaded == 0)   

                {

                    break;   

                }

            }

        }   

    }   

    

    // Close the HINTERNET handle   

    InternetCloseHandle(hRequest);   

    InternetCloseHandle(hSession);   

    InternetCloseHandle(hInternet);   

    

    // Set the cursor back to an arrow   

    SetCursor(LoadCursor(NULL,IDC_ARROW));   

}

==========================================

关文件:#include <afxinet.h>

使用MFC示例如下:   

    首先设置m_strRequest请求字符串       eg."name=aaa&pass=bbb";               

                    m_strServerName     服务器名称或者IP       eg."www.yahoo.com"   

                    m_strObjectName     请求文件位置     eg.     "pub/aaa.asp"   

        请求的结果存放在m_strHtml中   

void func()

{   

    CInternetSession m_InetSession("session");

    CHttpConnection *pServer = NULL;

    CHttpFile* pFile = NULL;   

    try

    {   

        INTERNET_PORT nPort;

        nPort=80;

        pServer = m_InetSession.GetHttpConnection(m_strServerName, nPort);

        pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST,m_strObjectName);

        char szHeaders[100];

        strcpy(szHeaders,"Accept: text*/*/r/nContent-Type: application/x-www-form-urlencoded");

        pFile->AddRequestHeaders(szHeaders);

        

        pFile->SendRequestEx(m_strRequest.GetLength());   

        pFile->WriteString(m_strRequest);//重要-->m_Request 中有"name=aaa&name2=BBB&"

        pFile->EndRequest();

        DWORD dwRet;

        pFile->QueryInfoStatusCode(dwRet);

        CString str;

        

        //m_Mutex.Lock();

        m_strHtml="";

        char szBuff[1024];

        if (dwRet == HTTP_STATUS_OK)

        {

            UINT nRead;   

            while ((nRead = pFile->Read(szBuff,1023))>0)   

            {   

                m_strHtml += CString(szBuff,nRead);   

            }

        }

        //m_Mutex.Unlock();   

        

        delete pFile;   

        delete pServer;   

    }   

    catch (CInternetException* e)

    {   

        CString s;   

        s.Format("Internet Exception/r/nm_dwError%u,m_dwContextError%u",e->m_dwError,e->m_dwContext);   

        AfxMessageBox(s);   

        //catch errors from WinInet   

    }   

}

============================

1、获得WebBrowser     Control的DWebBrowserEvents2::DocumentComplete事件   

    2、在DWebBrowserEvents2::DocumentComplete事件中根据IWebBrowser2::Document获得IHTMLDocument2   

    3、IHTMLDocument2::forms得到IHTMLElementCollection   

    4、在IHTMLElementCollection中根据name、tagName、ID得到指定的IHTMLElement   

    5、从IHTMLElement得到IHTMLFormElement   

    6、执行IHTMLFormElement::submit

==================================================

要正确模拟表单提交使用 WinInet, 您需要发送一个指示正确 Content-Type 标头。 对于窗体, 正确 Content-Type 标题是:

Content-Type: application/x-www-form-urlencoded

如果没有指定 Content-Type 在许多情况下, 服务器不响应正确。 在之前将表单变量添加到 " Request.Form "

对象例如, IIS 3.0 的 ActiveServerPages 组件实际上检查专门用于应用表单 ' www 程序 / x -

urlencoded ' 此标题。 此 MIME / 内容类型指示请求数据是 - URL 编码窗体变量的列表。 URL 编码意味着空格字符

(ASCII 32) 被编码为 + ' ', 特殊字符如 ' ! ' 以十六进制形式编码为 21 % '。

下面是使用 MFCWinInet 类来模拟 FormPOST 请求的代码段:

   CString strHeaders =

      _T("Content-Type: application/x-www-form-urlencoded");

   // URL-encoded form variables -

   // name = "John Doe", userid = "hithere", other = "P&Q"

   CString strFormData = _T("name=John+Doe&userid=hithere&other=P%26Q");

   CInternetSession session;

   CHttpConnection* pConnection =

      session.GetHttpConnection(_T("ServerNameHere"));

   CHttpFile* pFile =

      pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,

                              _T("FormActionHere"));

   BOOL result = pFile->SendRequest(strHeaders,

      (LPVOID)(LPCTSTR)strFormData, strFormData.GetLength());

    

没有 MFC, 相同的代码将转换为直 SDK 调用如下:

   static TCHAR hdrs[] =

      _T("Content-Type: application/x-www-form-urlencoded");

   static TCHAR frmdata[] =

      _T("name=John+Doe&userid=hithere&other=P%26Q");

  static LPSTR accept[2]={"*/*", NULL};

   // for clarity, error-checking has been removed

   HINTERNET hSession = InternetOpen("MyAgent",

      INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);

   HINTERNET hConnect = InternetConnect(hSession, _T("ServerNameHere"),

      INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);

   HINTERNET hRequest = HttpOpenRequest(hConnect, "POST",

      _T("FormActionHere"), NULL, NULL, accept, 0, 1);

   HttpSendRequest(hRequest, hdrs, strlen(hdrs), frmdata, strlen(frmdata));

   // close any valid internet-handles

===================================================

    

Get资料:

#include "winsock2.h"

#include "stdio.h"

#include "Wininet.h"

#pragma comment (lib,"Wininet.lib")

void main()

{

HINTERNET hNet = ::InternetOpen("Google page", //当HTTP协议使用时,这个参数随意赋值

PRE_CONFIG_INTERNET_ACCESS, //访问类型指示Win32网络函数使用登记信息去发现一个服务器。

NULL,

INTERNET_INVALID_PORT_NUMBER, //使用INTERNET_INVALID_PORT_NUMBER相当于提供却省的端口数。

0 //标志去指示使用返回句句柄的将来的Internet函数将"不"为回调函数发送状态信息

) ;

HINTERNET hUrlFile = ::InternetOpenUrl(hNet, //从InternetOpen返回的句柄

"http://www.google.com", //需要打开的URL

NULL, //用来向服务器传送额外的信息,一般为NULL

0, //用来向服务器传送额外的信息,一般为 0

INTERNET_FLAG_RELOAD, //InternetOpenUrl行为的标志

0) ; //信息将不会被送到状态回调函数

char buffer[1024] ;

DWORD dwBytesRead = 0;

BOOL bRead = ::InternetReadFile(hUrlFile, //InternetOpenUrl返回的句柄

buffer, //保留数据的缓冲区

sizeof(buffer),

&dwBytesRead); //指向包含读入缓冲区字节数的变量的指针;

//如果返回值是TRUE,而且这里指向0,则文件已经读到了文件的末尾。

::InternetCloseHandle(hUrlFile) ;

::InternetCloseHandle(hNet) ;

printf("%s", buffer);

}


你可能感兴趣的:(在VC中WININET使用HTTP的POSTA和GET方法)