您的位置:首页 > 理论基础 > 计算机网络

C++写的与http交互的类CHttpClient

2013-12-06 16:01 288 查看
源文件下载和使用案例http://www.codeproject.com/KB/library/lyoulhttpclient.aspx?fid=82827&tid=3076061

Introduction

CHttpClient
is a helper class using WinInet API. The purpose of this class is to help you interact with a HTTP web server. The class design goal is as follows:
Easy to use.
As many flexibilities as possible.
Strict error handling.
I will briefly show you how to use this class. All detailed description has been documented in the attached help file.

How to use CHttpClient

In your project, include the following files:
RyeolException.h
RyeolException.cpp
RyeolHttpClient.h
RyeolHttpClient.cpp
SafeInt.hpp
In your stdafx.h file, add the following line:


Collapse
#include "RyeolHttpClient.h"
Note: The namespace and file names have been changed. If you use the previous version of the
CHttpClient
, you need to update as follows:
LyoulException.h --> RyeolException.h
LyoulException.cpp --> RyeolException.cpp
LyoulHttpClient.h --> RyeolHttpClient.h
LyoulHttpClient.cpp --> RyeolHttpClient.cpp
#include "LyoulHttpClient.h" --> #include "RyeolHttpClient.h"
using namespace Lyoul --> using namespace Ryeol

How to Send a Request Using HTTP GET

CHttpClient
supports
RequestGet
method which sends a request using HTTP GET:


Collapse
// Retrieves the resource specified by the szUrl using HTTP GET request.

// szUrl            [in] A HTTP URL.

// bUseCache        [in] Specifies whether to use cache.

CHttpResponse * CHttpClient::RequestGet (PCSZ szUrl, 
   BOOL bUseCache = FALSE) throw (Exception &) ;
The following code demonstrates the basic usage of the
RequestGet
method:


Collapse
using namespace Ryeol ;

CHttpClient         objHttpReq ;
CHttpResponse *     pobjHttpRes = NULL ;

try {
    // Initialize the User Agent

    objHttpReq.SetInternet (_T ("My User Agent v1.0")) ;

    // Specifies whether to use UTF-8 encoding. 

    // (This uses ANSI encoding)

    // Default is FALSE

    objHttpReq.SetUseUtf8 (FALSE) ;

    // Specifies a code page for ANSI strings. 

    // (This uses Korean)

    // Default is CP_ACP

    objHttpReq.SetAnsiCodePage (949) ;

    // Add user's custom HTTP headers

    objHttpReq.AddHeader (_T ("Ryeol-Magic"), _T ("My Magic Header")) ;
    objHttpReq.AddHeader (_T ("User-Magic"), _T ("User's Magic Header")) ;

    // Add user's parameters

    objHttpReq.AddParam (_T ("where"), _T ("nexearch")) ;
    objHttpReq.AddParam (_T ("frm"), _T ("t1")) ;
    objHttpReq.AddParam (_T ("query"), 
       _T ("%C3%D6%C1%F6%BF%EC"), CHttpClient::ParamEncodedValue) ;

    // Send a request

    pobjHttpRes = 
      objHttpReq.RequestGet (_T ("http://search.naver.com/search.naver")) ;

    ...     // Place codes to handle the returned CHttpResponse object.

} catch (httpclientexception & e) {
    ...     // Place exception handling codes here.

}

How to Send a Request Using HTTP POST

The HTTP POST method is used in two ways. One is to post simple text, the other is to upload files. To post simple text,
CHttpClient
provides
BeginPost
method.


Collapse
// Starts a new HTTP POST request

// szUrl            [in] A HTTP URL.

// bUseCache        [in] Specifies whether to use cache.

void CHttpClient::BeginPost (PCSZ szUrl, 
   BOOL bUseCache = FALSE) throw (Exception &) ;
The following code demonstrates the basic usage of the
BeginPost
method:


Collapse
using namespace Ryeol ;

CHttpClient         objHttpReq ;
CHttpResponse *     pobjHttpRes = NULL ;

try {
    // Initialize the User Agent

    objHttpReq.SetInternet (_T ("My User Agent v1.0")) ;

    // Add user's custom HTTP headers

    objHttpReq.AddHeader (_T ("Ryeol-Magic"), _T ("My Magic Header")) ;
    objHttpReq.AddHeader (_T ("User-Magic"), _T ("User's Magic Header")) ;

    // Add user's parameters

    objHttpReq.AddParam (_T ("st"), _T ("kw")) ;
    objHttpReq.AddParam (_T ("target"), _T ("WinInet")) ;

    // Start a new request

    objHttpReq.BeginPost (_T ("http://www.codeproject.com/info/search.asp")) ;

    // Specifies the number of bytes to send when the Proceed method is called.

    const DWORD     cbProceed = 1024 ;  // 1K

    do {

        ...     // Place codes to report progress information to user.

    } while ( !(pobjHttpRes = objHttpReq.Proceed (cbProceed)) ) ;
    ...     // Place codes to handle the returned CHttpResponse object.

} catch (httpclientexception & e) {
    ...     // Place exception handling codes here.

}
To upload file,
CHttpClient
provides
BeginUpload
method.


Collapse
// Starts a new UPLOAD request

// szUrl            [in] A HTTP URL.

// bUseCache        [in] Specifies whether to use cache.

void CHttpClient::BeginUpload (PCSZ szUrl, 
   BOOL bUseCache = FALSE) throw (Exception &) ;
The following code demonstrates the basic usage of the
BeginUpload
method:


Collapse
using namespace Ryeol ;

CHttpClient         objHttpReq ;
CHttpResponse *     pobjHttpRes = NULL ;

try {
    // Initialize the User Agent

    objHttpReq.SetInternet (_T ("My User Agent v1.0")) ;

    // Add user's custom HTTP headers

    objHttpReq.AddHeader (_T ("Ryeol-Magic"), _T ("My Magic Header")) ;
    objHttpReq.AddHeader (_T ("User-Magic"), _T ("User's Magic Header")) ;

    // Add user's parameters

    objHttpReq.AddParam (_T ("nohtml"), _T ("1")) ;
    objHttpReq.AddParam (_T ("title"), _T ("The K-NET photo")) ;
    objHttpReq.AddParam (_T ("content"), _T ("A photo of the K-NET")) ;

    // Specifies a file to upload

    objHttpReq.AddParam (_T ("ufile01"), 
       _T ("D://My Photo//K-NET//photo1.jpg"), 
       CHttpClient::ParamFile) ;

    // Start a new request

    objHttpReq.BeginUpload (_T ("http://club.hooriza.com")
       _T ("/cmd/box.html?clubid=1&boxid=53&action=store&link=")) ;

    // Specifies the number of bytes to send when the Proceed method is called.

    const DWORD     cbProceed = 1024 ;  // 1K

    do {

        ...     // Place codes to report progress information to user.

    } while ( !(pobjHttpRes = objHttpReq.Proceed (cbProceed)) ) ;
    ...     // Place codes to handle the returned CHttpResponse object.

} catch (httpclientexception && e) {
    ...     // Place exception handling codes here.

}

How to Handle the Returned CHttpResponse Object

When you send a request using
CHttpClient
, all the methods will return
CHttpResponse
object.
CHttpResponse
represents the response returned by a HTTP web server.
CHttpResponse
provides the following methods:


Collapse
// Returns the number of headers of which name is the szName

DWORD CHttpResponse::GetHeaderCount (PCSZ szName) throw (Exception &) ;

// Returns the header of which name is the szName

PCSZ CHttpResponse::GetHeader (PCSZ szName, 
          DWORD nIdx = 0) throw (Exception &) ;

// Returns the HTTP status code returned by a HTTP server

DWORD CHttpResponse::GetStatus (void) throw (Exception &) ;

// Returns the HTTP status text returned by a HTTP server

PCSZ CHttpResponse::GetStatusText (void) throw (Exception &) ;

// Retrieves the length of the content returned by a HTTP server

BOOL CHttpResponse::GetContentLength (DWORD & cbContLen) throw (Exception &) ;

// Reads the content returned by a HTTP server

DWORD CHttpResponse::ReadContent (BYTE * pbyBuff, 
          DWORD cbBuff) throw (Exception &) ;
The following code demonstrates the basic usage of the
CHttpResponse
object:


Collapse
using namespace Ryeol ;

CHttpResponse *     pobjHttpRes = NULL ;

try {
    // Get the CHttpResponse object

    pobjHttpRes = ... ;

    // Reads the HTTP status code

    _tprintf (_T ("%u"), pobjHttpRes->GetStatus ()) ;
    // Reads the HTTP status text

    _tprintf (_T (" %s/n"), pobjHttpRes->GetStatusText ()) ;

    // Reads HTTP headers using an array of header names

    static LPCTSTR      szHeaders[] = 
    { _T ("Server"), _T ("Date"), _T ("X-Powered-By"), 
                _T ("Content-Length"), _T ("Set-Cookie")
    , _T ("Expires"), _T ("Cache-control"), 
                _T ("Connection"), _T ("Transfer-Encoding")
    , _T ("Content-Type") } ;

    LPCTSTR     szHeader ;
    for (size_t i = 0; i < sizeof (szHeaders) / sizeof (LPCTSTR); i++) {
        if ( szHeader = pobjHttpRes->GetHeader (szHeaders[i]) )
            _tprintf (_T ("%s: %s/n"), szHeaders[i], szHeader) ;
        else
            // If the header is not found..

            _tprintf (_T ("'%s' header does not exist../n"), 
                                                    szHeaders[i]) ;
    }
    _tprintf (_T ("/n")) ;

    // Checks whether the returned stream is a text

    BOOL        bIsText = FALSE ;
    if ( szHeader = pobjHttpRes->GetHeader (_T ("Content-Type")) )
        bIsText = (0 == ::_tcsncicmp (szHeader, _T ("text/"), 5)) ;

    // Reads the length of the stream

    DWORD       dwContSize ;
    // If the length is not specified

    if ( !pobjHttpRes->GetContentLength (dwContSize) )
        dwContSize = 0 ;

    const DWORD     cbBuff = 1024 * 10 ;
    BYTE            byBuff[cbBuff] ;
    DWORD           dwRead ;
    size_t          cbTotal = 0 ;

    // Reads the data stream returned by the HTTP server.

    while ( dwRead = pobjHttpRes->ReadContent (byBuff, cbBuff - 1) ) {
        cbTotal += dwRead ;

        if ( bIsText ) {
            byBuff[dwRead] = '/0' ;
            printf ("%s", reinterpret_cast<LPCSTR> (byBuff)) ;
        }
    }
    if ( !bIsText )
        _tprintf (_T ("%u bytes skipped../n"), cbTotal) ;
} catch (httpclientexception & e) {
    ...     // Place exception handling codes here.

}
delete pobjHttpRes ;
pobjHttpRes = NULL ;

How to Handle Exception

When an error occurs,
httpclientexception
object is thrown:


Collapse
class httpclientexception {
public:
    // Returns the last error code.

    // The error codes is defined in RyeolHttpClient.h

    DWORD LastError (void) const throw () ;

    // Returns the last error message.

    LPCTSTR errmsg (void) const throw () ;

    // Returns the last win32 error code retrieved by

    // using ::GetLastError when an error occurred.

    DWORD Win32LastError (void) const throw () ;
} ;
Before throwing an exception, most methods restore their internal states (all or nothing like transaction). But if you call
BeginPost
or
BeginUpload
method, the POST context is automatically canceled. You should write the following
try
-
catch
block to handle the exception:


Collapse
using namespace Ryeol ;

try {
    ...     // Place codes which throw a httpclientexception exception

} catch (httpclientexception & e) {
    _tprintf (_T ("An error has been occured/n")) ;
    _tprintf (_T ("ErrCode: 0x%x/n"), e.LastError ()) ;
    _tprintf (_T ("ErrMsg: %s/n"), e.errmsg ()) ;
    if ( e.Win32LastError () != NO_ERROR ) {
        TCHAR       szErrMsg[512] ;
        GetWinInetErrMsg (szErrMsg, 512, e.Win32LastError ()) ;

        _tprintf (_T ("Win32ErrCode: 0x%x/n"), e.Win32LastError ()) ;
        _tprintf (_T ("Win32ErrMsg: %s/n"), szErrMsg) ;
    }
}

How to Show the Progress Information to the User

If you call
BeginPost
or
BeginUpload
method, you can retrieve the progress information using the
Query
method:


Collapse
// Queries progress information of the current POST context

// objPostStat      [out] A CHttpPostStat object.

void CHttpClient::Query (CHttpPostStat & objPostStat) throw () ;
CHttpPostStat
represents the progress information of the current POST context. The following code demonstrates the basic usage of the
CHttpPostStat
object:


Collapse
using namespace Ryeol ;

CHttpClient         objHttpReq ;
CHttpResponse *     pobjHttpRes = NULL ;
size_t              cbProceed = 1024 ;  // 1k

try {
    ... ;   // Intialize the CHttpClient object

    // Starts a new POST request

    objHttpReq.BeginPost (...) or objHttpReq.BeginUpload (...) ;

    // Displays progress information

    CHttpPostStat       objPostStat ;
    do {
        // Retrieves progress information

        objHttpReq.Query (objPostStat) ;

        _tprintf (_T ("/nPost in progress... %2u/%2u/n")
            , objPostStat.PostedCount ()   // The number of posted parameters

            , objPostStat.TotalCount ()) ; // The total number of parameters

        _tprintf (_T ("%s: %10u/%10u %10u/%10u %10u/%10u/n")
            // The name of the current parameter

            , objPostStat.CurrParam ()
            // The number of posted bytes of the current parameter

            , objPostStat.CurrParamPostedByte ()
            // The total number of bytes of the current parameter

            , objPostStat.CurrParamTotalByte ()
            // The number of posted bytes of the request

            , objPostStat.PostedByte ()
            // The total number of bytes of the request

            , objPostStat.TotalByte ()
            // The actual number of posted bytes of the request

            , objPostStat.ActualPostedByte ()
            // The actual total number of bytes of the request

            , objPostStat.ActualTotalByte ()) ;

        // If the current parameter is a file parameter,

        // displays the file path

        if ( objPostStat.CurrParamIsFile () )
            _tprintf (_T ("-->%s/n")
                , objPostStat.CurrFile ()) ;
        // Sends the number of bytes specified by cbProceed to the server

    } while ( !(pobjHttpRes = objHttpReq.Proceed (cbProceed)) ) ;
    ... ;   // Handles the returned CHttpResponse object

} catch (httpclientexception & e) {
    ...     // Place exception handling codes here.

}

About CHttpClient COM Edition

CHttpClient
COM Edition is the component version of
CHttpClient
. I won't explain here how to use it because it is similar to
CHttpClient
. You can refer to the attached examples and the help file of
CHttpClient
COM edition. If you want to use
CHttpClient
COM edition, you need to installRyeolHttpClient2.dll. Because it is a COM DLL, you have to register it by using the regsvr32.exe program. You can install it anywhere you want provided you don't distribute it. But if you want to distribute it, I recommend that you install it in the %WINDOWS%System32 folder and do not remove it even if your program is uninstalled.

History

3rd February, 2006The assertion behavior has been changed to throw an exception if the assertion expression is failed.
The pragma warning (push) and (pop) directives are used to restore the previous warning state.
The
SaveContent
method has been added.
The namespace and file names have been changed.
CHttpClient COM Edition has been added.

9th August, 2004Some methods have been added to support proxy authorization.

29th July, 2004Initial release.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.
A list of licenses authors might use can be found here

About the Author

JO Hyeong-Ryeol

Software Developer
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: