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

 

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

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
使用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);

你可能感兴趣的:(asp及网络,C,mfc,internet,null,variables,buffer,delete,mfc)