关于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.</br>
*
* @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 <b>Summary:</b>
* Initiate this CURL session
* @return 0, if success. <br>
* -1, if failed.
*******************************************************************************/
int init();
protected:
/**
* @brief <b>Summary:</b>
* This function is virtual function, which will be called by automatic,
* as soon as there is data received that needs to be processed.<br>
* The size of the data pointed to by 'data' is 'size' multiplied with 'nmemb',
* it will not be zero terminated. <br>
* @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 <b>Summary:</b>
* 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. </br>
* -1, if failed.
*******************************************************************************/
int doHttpPost( const char* url, const char* data, long timeout = 10, long withheader = 0 );
/**
* @brief <b>Summary:</b>
* 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. </br>
* -1, if failed.
*******************************************************************************/
int doHttpGet( const char* url, const char* data, long timeout = 10, long withheader = 0 );
public:
//CURLcode setOpt( CURLoption option );
/**
* @brief <b>Summary:</b>
* Reset all options of a libcurl session handle
* @return void, no return
*******************************************************************************/
void resetOpt();
private:
/**
* @brief <b>Summary:</b>
* This function gets called by libcurl as soon as there is data received
* that needs to be saved.<br>
* The size of the data pointed to by ptr is size multiplied with nmemb,
* it will not be zero terminated. <br>
* @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. <br>
* 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 );/**<Upload to this url place*/
// ::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 = "http://forum.byr.edu.cn/wForum/logon.php";
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, "http://192.168.3.200:8080/action.get.php", name, age );
cu.doHttpGet( url, data, 10, 1 );
}
// void testCCUrlUploadFile( const char* filename )
// {
// CCUrl cu;
// cu.init();
// char url[1024];
// sprintf( url, "http://192.168.3.200:8080/%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 = "http://forum.byr.edu.cn/wForum/logon.php";
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 = "http://192.168.3.200:8080/action.get.php";
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 = "http://192.168.3.200:8080/action.get.php";
cu2->doHttpGet( url, data, 10 );
delete cu2;
url = "http://forum.byr.edu.cn/wForum/logon.php";
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。直接用就可以了。
原文地址:http://blog.chinaunix.net/uid-20384806-id-1954334.html