Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4203872
  • 博文数量: 176
  • 博客积分: 10059
  • 博客等级: 上将
  • 技术积分: 4681
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-24 12:27
文章分类

全部博文(176)

文章存档

2012年(1)

2011年(4)

2010年(14)

2009年(71)

2008年(103)

分类: C/C++

2009-06-09 15:03:22

关于curl的基本用法请见curl的官网(http://curl.haxx.se/) 以及我的前一篇转载别人的博文:http://blog.chinaunix.net/u/16292/showart_1951736.html 。

本文给出一个 curl 的简单 c++ 封装类,以及测试用例。

头文件:

/**
 * @file HCUrl.h
 *
 * @brief
 * The CCUrl class header file.

 *
 * @author zieckey
 *
 * @date Jun. 3 2009
 *
 * @version 0.0.1
 *
 * Revision History
 * @if CR/PR ID Author    Date    Major Change @endif
 * @bug \n
****************************************************************************/


#ifndef __CCUrl_H__
#define __CCUrl_H__

#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>

#include <string.h>

namespace OSLib
{
    //const long CLIENTTIMEOUT = 10;


    /*! @class CCUrl CCUrl.h "CCUrl.h"
    * @brief This is the CCUrl class, a wrapper of libcurl.
    *
    */

    class CCUrl
    {
    public:
        CCUrl();
        virtual ~CCUrl();
    
        /**
        * @brief Summary:
        *    Initiate this CURL session
        * @return    0, if success.

        *            -1, if failed.
        *******************************************************************************/

        int    init();
    
    protected:
        /**
        * @brief Summary:
        *        This function is virtual function, which will be called by automatic,
        *    as soon as there is data received that needs to be processed.

        *        The size of the data pointed to by 'data' is 'size' multiplied with 'nmemb',
        *    it will not be zero terminated.

        * @note    You should override this function to do you own busyness.
        *        You save the data to a file, or process it anyway.
        * @param[in] data, point to the data
        * @param[in] size, the size        
        * @param[in] nmemb, the unit in bytes        
        * @return
        *****************************************************************************/

        virtual int process( void* data, size_t size, size_t nmemb );

    public:
        /**
        * @brief Summary:
        *    Post 'data' to 'url', and the server response data is restored in resultData.
        *    The process function is 'pfun'
        * @param[in]    url
        * @param[in]    data, the data to be sent to server.
        *                    eg. "id=admin&passwd=123456"
        * @param[in]    timeout, the limit time in seconds to do this process.
        *                    default value 10
        * @param[in]    withheader,
        *                    1 indicate the server response data including header
        *                    0 indicate the server response data excluding header
        *                    default value 0
        * @return    0, if success.

        *            -1, if failed.
        *******************************************************************************/

        int doHttpPost( const char* url, const char* data, long timeout = 10, long withheader = 0 );

        /**
        * @brief Summary:
        *    Get 'url' using 'data' to be set in the header,
        *    and the server response data is restored in resultData.
        *    The process function is 'pfun'
        * @param[in]    url
        * @param[in]    data, the data to be sent to server.
        *                    eg. "id=admin&passwd=123456"
        * @param[in]    timeout, the limit time in seconds to do this process.
        *                    default value 10
        * @param[in]    withheader,
        *                    1 indicate the server response data including header
        *                    0 indicate the server response data excluding header
        *                    default value 0
        * @return    0, if success.

        *            -1, if failed.
        *******************************************************************************/

        int doHttpGet( const char* url, const char* data, long timeout = 10, long withheader = 0 );


    public:
        //CURLcode setOpt( CURLoption option );


        /**
        * @brief Summary:
        *    Reset all options of a libcurl session handle
        * @return void, no return
        *******************************************************************************/

        void resetOpt();
        
    private:
        /**
        * @brief Summary:
        *        This function gets called by libcurl as soon as there is data received
        *    that needs to be saved.

        *        The size of the data pointed to by ptr is size multiplied with nmemb,
        *    it will not be zero terminated.

        * @param[in]
        * @param[in]    
        * @param[in]    
        * @param[in] usrptr, the user ptr,
        *            set by option CURLOPT_READDATA or CURLOPT_WRITEDATA...
        * @return    the number of bytes actually taken care of.

        *        If that amount differs from the amount passed to your function,
        *    it'll signal an error to the library and it will abort the transfer
        *    and return CURLE_WRITE_ERROR.
        *****************************************************************************/

        static size_t processFunc( void* ptr, size_t size, size_t nmemb, void *usrptr );

    private:
        CURL * m_curl;
    };    
};

#endif

实现文件:

#include "HCUrl.h"

namespace OSLib
{

    CCUrl::CCUrl() : m_curl(NULL)
    {
    }
    
    CCUrl::~CCUrl()
    {
        ::curl_easy_cleanup( m_curl );
        ::curl_global_cleanup();
    }

    int CCUrl::init()
    {
        CURLcode res = ::curl_global_init( CURL_GLOBAL_ALL );
        if( CURLE_OK != res )
        {
            fprintf( stderr, "curl_global_init failed: %d \n", res );
            return -1;
        }
    
        m_curl = ::curl_easy_init();
        if( NULL == m_curl )
        {
            fprintf( stderr, "curl_easy_init failed\n" );
            return -1;
        }
        return 0;
    }


    int CCUrl::doHttpPost( const char* url, const char* data, long timeout, long withheader )
    {
        resetOpt();
        ::curl_easy_setopt( m_curl, CURLOPT_HEADER, withheader );
        ::curl_easy_setopt( m_curl, CURLOPT_URL, url );
        ::curl_easy_setopt( m_curl, CURLOPT_POST, 1 );
        ::curl_easy_setopt( m_curl, CURLOPT_POSTFIELDS, data );
        ::curl_easy_setopt( m_curl, CURLOPT_TIMEOUT, timeout );
        ::curl_easy_setopt( m_curl, CURLOPT_WRITEFUNCTION, CCUrl::processFunc );
        ::curl_easy_setopt( m_curl, CURLOPT_WRITEDATA, this );
        CURLcode res = ::curl_easy_perform( m_curl);
        return ( 0 == res ) ? 0 : -1;
    }

    int CCUrl::doHttpGet( const char* url, const char* data, long timeout, long withheader )
    {
        resetOpt();
        size_t urllen = strlen( url );
        size_t datalen = strlen( data );
        char* surl = new char[ urllen + datalen + 1 + 1];
        if( !surl )
        {
            fprintf( stderr, "doHttpGet failed, unable to malloc memery\n" );
            return -1;
        }
        strncpy( surl, url, urllen );
        surl[ urllen ] = '?';
        strcpy( surl + urllen + 1, data );
        ::curl_easy_setopt( m_curl, CURLOPT_URL, surl );
        ::curl_easy_setopt( m_curl, CURLOPT_HTTPGET, 1 );
        ::curl_easy_setopt( m_curl, CURLOPT_HEADER, withheader );
        ::curl_easy_setopt( m_curl, CURLOPT_TIMEOUT, timeout );
        ::curl_easy_setopt( m_curl, CURLOPT_WRITEFUNCTION, CCUrl::processFunc );
        ::curl_easy_setopt( m_curl, CURLOPT_WRITEDATA, this );

        CURLcode res = ::curl_easy_perform( m_curl);

        delete [] surl;
        return ( 0 == res ) ? 0 : -1;
    }

    void CCUrl::resetOpt()
    {
        ::curl_easy_reset( m_curl );
        //::curl_easy_setopt( m_curl, CURLOPT_VERBOSE, 1 );//set this to show debug message

    }

    size_t CCUrl::processFunc( void* ptr, size_t size, size_t nmemb, void *usrptr )
    {
        CCUrl* p =(CCUrl*) usrptr;
        return p->process( ptr, size, nmemb );
    }
    


    int CCUrl::process( void* data, size_t size, size_t nmemb )
    {
        printf( "\n ===== CCUrl::process( void* data, size_t size, size_t nmemb ) ===== \n" );
        return size * nmemb;
    }

//     int CCUrl::uploadFile( const char* url, const char* localfilename )

//     {

//         m_upfilename = (char*)localfilename;

//         resetOpt();

//         ::curl_easy_setopt( m_curl, CURLOPT_URL, url );/**
//         ::curl_easy_setopt( m_curl, CURLOPT_UPLOAD, 1 );

//         ::curl_easy_setopt( m_curl, CURLOPT_READFUNCTION, CCUrl::uploadFileReadFunc );

//         ::curl_easy_setopt( m_curl, CURLOPT_READDATA, this );

//         CURLcode res = ::curl_easy_perform( m_curl);

//         return ( 0 == res ) ? 0 : -1;

//     }

//

//     size_t CCUrl::uploadFileReadFunc( void* ptr, size_t size, size_t nmemb, void *usrptr )

//     {

//         CCUrl* p =(CCUrl*) usrptr;

//         static FILE* pf = NULL;

//         if( !pf )

//         {

//             pf = fopen( p->m_upfilename, "r" );

//             if( !pf )    

//             {

//                 fprintf( stderr, "cannot open file: %s \n", p->m_upfilename );

//                 return 0;

//             }

//         }

//

//         if( pf )

//         {

//             int nread = fread( ptr, size, nmemb, pf );

//             if( !nread )

//             {

//                 fclose( pf );

//                 pf = NULL;    

//             }

//             

//             return nread;

//         }

//

//         return 0;

//     }



}; //end namespace

测试程序:

 

#include "HCUrl.h"

#include <string.h>

using namespace OSLib;

class MyCCUrl : public CCUrl
{
protected:
    int process( void* data, size_t size, size_t nmemb )
    {
        //printf( "\n================entering size=%d================\n", size * nmemb );

        printf( "%s", (char*)data );
        return size * nmemb;
    }    
};


void testCCUrlDoHttpPost( const char* username, const char* password );
void testCCUrlDoHttpGet( const char* name, const char* age );
void testGlobalCleanup( const char* username, const char* password );
void testCCUrlUploadFile( const char* filename );

int main( int argc, char* argv[] )
{
//     if( argc < 3 )        

//     {

//         printf( "usage:%s username password\n", argv[0] );

//         return 0;

//     }

//     testCCUrlDoHttpPost( argv[1], argv[2] );



    if( argc < 3 )        
    {
        printf( "usage:%s name age\n", argv[0] );
        return 0;
    }
    testCCUrlDoHttpGet( argv[1], argv[2] );

//     if( argc < 3 )        

//     {

//         printf( "usage:%s username password\n", argv[0] );

//         return 0;

//     }

//     testGlobalCleanup( argv[1], argv[2] );

    
//     if( argc < 2 )        

//     {

//         printf( "usage:%s filename\n", argv[0] );

//         return 0;

//     }

//     testCCUrlUploadFile( argv[1] );

    
    return 0;
}


void testCCUrlDoHttpPost( const char* username, const char* password )
{
    MyCCUrl cu;
    cu.init();
    char data[1024];
    sprintf( data, "id=%s&passwd=%s", username, password );
    char buf[1024 * 1024];
    char* url = "";
    cu.doHttpPost( url, data, 10 );
}

void testCCUrlDoHttpGet( const char* name, const char* age )
{
    MyCCUrl cu;
    cu.init();
    char data[1024];
    sprintf( data, "name=%s&age=%s", name, age );
    char buf[1024 * 1024];
    char url[1024];
    sprintf( url, "", name, age );
    cu.doHttpGet( url, data, 10, 1 );
}

// void testCCUrlUploadFile( const char* filename )

// {

//     CCUrl cu;

//     cu.init();

//     char url[1024];

//     sprintf( url, "%s", filename );

//     cu.uploadFile( url, filename );

// }



void testGlobalCleanup( const char* username, const char* password )
{
    for ( int i = 0; i < 10; i ++ )
    {
        MyCCUrl* cu = new MyCCUrl;
        cu->init();
        char data[1024];
        sprintf( data, "id=%s&passwd=%s", username, password );
        char* url = "";
        cu->doHttpPost( url, data, 10 );
    
        printf( "\n\n\n=============================================\n\n\n" );
    
        MyCCUrl* cu2 = new MyCCUrl;
        
        cu2->init();
        sprintf( data, "name=%s&age=%s", username, password );
        url = "";
        
        delete cu;    //check after deleting cu, whether cu2 is ok


        cu2->doHttpGet( url, data, 10 );
        
        delete cu2;
    }

    for ( int i = 0; i < 10; i ++ )
    {
        MyCCUrl* cu = new MyCCUrl;
        cu->init();
        char data[1024];
        char* url = 0;
        
    
        printf( "\n\n\n=============================================\n\n\n" );
    
        MyCCUrl* cu2 = new MyCCUrl;
        
        cu2->init();
        sprintf( data, "name=%s&age=%s", username, password );
        url = "";
        cu2->doHttpGet( url, data, 10 );
        delete cu2;
        
        url = "";
        sprintf( data, "id=%s&passwd=%s", username, password );
        cu->doHttpPost( url, data, 10 );
        delete cu;    //check after deleting cu, whether cu2 is ok

    }
}

测试中用到了一个php脚本,用于web服务器端解析:

<html>
     <head>
      <title>PHP action</title>
     </head>
     <body>
        your name is: <?php echo htmlspecialchars($_GET['name']); ?> </br>
        your age is: <?php echo (int)$_GET['age']; ?>
</body>
</html>

可以把main函数中的测试get的方法注释掉,把测试post的部分代码打开,就可以测试post了。post的测试例子用到的url是一个论坛的登录url。直接用就可以了。

阅读(15386) | 评论(1) | 转发(1) |
给主人留下些什么吧!~~

chinaunix网友2010-09-21 09:45:29

lvselieren: 好东西,谢谢啊!