curl簡單介紹

 關於Curl的介紹很多,這裏不詳細介紹,主要談一下簡單應用。
最近研究了一下Linux下的curl C API,最新版本爲7.17,curl c API的文檔比較豐富,唯一就是查找起來,費些時間。Curl的C API和curl的PHP API,函數接口和作用大致相同,所以如果有PHP API使用經驗應該很好理解。
         基於curl 的C API寫了一個擴展C++ singleton類(當然curl也有C++ API),這個單體類只是對HTTP請求做了簡單封裝,提供post,get方法,並得到請求url內的返回值(保存到string對象中),也很容易擴展到其他協議上去。
Curlplus.h文件
#ifndef _CURLPLUS_H__
#define _CURLPLUS_H__
#ifndef __CURL_CURL_H
#include <curl/curl.h>
#endif
#ifndef __CURL_EASY_H
#include <curl/easy.h>
#endif
#include <memory>
#include <string>
using namespace::std;
namespace CP
{
    class Curlplus
    {
    public:
        static Curlplus& get_instance();
        string post(const string& url,const string& content) const;
        string get(const string& url) const;
    protected:
        Curlplus(void);
        ~Curlplus(void);
        Curlplus(const Curlplus&);
        Curlplus& operator=(const Curlplus&);
        static int writer(char *data, size_t size, size_t nmemb,std::string *writerData);
    private:
        static auto_ptr<Curlplus> _instance;
        inline void _setCurlopt(CURL *curl,const string& url) const;
        // default timeout 300s
        static const int _defaulttimeout = 300;
        static string buffer;
        friend class auto_ptr<Curlplus>;
   
};
}
#endif
Curlpuls.cc文件
#ifndef SPIVOT_CURLPLUS_H__
#include "Curlplus.h"
#endif
using namespace std;
using namespace CP;
 
auto_ptr<Curlplus> Curlplus::_instance;
string Curlplus::buffer;
static char errorBuffer[CURL_ERROR_SIZE];
Curlplus& Curlplus::get_instance()
{
    if(_instance.get() == NULL)
    {
        _instance.reset(new Curlplus());
    } 
    return *_instance.get();
}
int Curlplus::writer(char *data, size_t size, size_t nmemb, string *writerData)
{
    if (writerData == NULL)
        return 0;
    int len = size*nmemb;
    writerData->append(data, len);
    return len;
}
Curlplus::Curlplus(void)
    CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
    if(code != CURLE_OK)
    {
        cout << "curl_init failed, error code is: " << code;
    }
}

Curlplus::~Curlplus(void)
{
    curl_global_cleanup();
}
string Curlplus::post(const string& url, const string& content) const
{
    buffer="";
    CURL *curl = curl_easy_init();
    if(curl == NULL)
    {
        cout << "curl_easy_init failed ";
    }  
    _setCurlopt(curl,url);
    curl_easy_setopt(curl, CURLOPT_POST, 1 );
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, content.c_str());   
    CURLcode code = curl_easy_perform(curl);
    if(code != CURLE_OK)
    {
        cout << "curl_easy_perform failed: "<< code;
    }
    curl_easy_cleanup(curl);
    return buffer;
}
string Curlplus::get(const string& url) const
{
    buffer="";
    CURL *curl = curl_easy_init();
    if(curl == NULL)
    {
        cout << "curl_easy_init failed ";
   
}  
    _setCurlopt(curl,url);
    CURLcode code = curl_easy_perform(curl); 
    if(code != CURLE_OK)
    {
        cout << "curl_easy_perform failed: "<< code;
    }
    curl_easy_cleanup(curl);
    return buffer;
}
void Curlplus::_setCurlopt(CURL *curl,const string& url) const {
    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
    curl_easy_setopt(curl, CURLOPT_HEADER, 0);
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, _defaulttimeout);
    //curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Curlplus::writer);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
}
這裏有幾個需要注意的地方
1:CURLcode curl_global_init(long flags);函數,這個函數全局需要調用一次(多次調用也可以,不過沒有必要), 所以這也是把Curlplus設計成單體類的原因,curl_global_init函數在其他libcurl函數調用前至少調用一次,程序最後需要調用curl_global_cleanup,進行清理。
參數:
flags
CURL_GLOBAL_ALL Initialize everything possible. This sets all known bits.
CURL_GLOBAL_SSL Initialize SSL
CURL_GLOBAL_WIN32 Initialize the Win32 socket libraries.
CURL_GLOBAL_NOTHING Initialise nothing extra. This sets no bit.
CURLcode 是一個enum,當CURLcode爲CURLE_OK時,表示函數執行成功,否則失敗,具體錯誤原因可以查看<curl/curl.h>文件內的定義。
2:curl_easy_init - Start a libcurl easy session
curl_easy_init用來初始化一個CURL的指針(有些像返回FILE類型的指針一樣). 相應的在調用結束時要用curl_easy_cleanup函數清理. 一般curl_easy_init意味着一個會話的開始. 它的返回值是CURL *,curl_easy_init函數是線程相關的,也就是說不能在一個線程中調用另外一個線程通過curl_easy_init創建的CURL指針。

3:CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);

描述: 這個函數最重要了.幾乎所有的curl 程序都要頻繁的使用它.它告訴curl庫.程序將有如何的行爲. 比如要查看一個網頁的html代碼等.,要想具體瞭解CURL的行爲,必須對CURLoption有足夠的瞭解,具體可以參考
這裏有兩個類型不易理解CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Curlplus::writer);
設置一個回調函數,這個回調函數的格式是
size_t function( void *ptr, size_t size, size_t nmemb, void *stream);
ptr,返回數據的指針
size,返回數據每塊的大小
nmemb,返回數據的塊數(這裏返回數據串的真正大小爲size*nmemb
stream,是curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); 中的buffer的指針。
在上面的例子中,buffer設置爲一個string對象,所以,在回調函數writer中有了writerData->append(data, len); 
4:CURLcode curl_easy_perform(CURL *handle);
執行遠程請求
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章