简单封装 libcurl

用到的库:

  • libcurl(必须)
  • boost(非必须)

其中,boost 库用作编码转换(当然了如果你不转换编码我也拦不了你…)
这个样例不仅有 get / post 操作,我还扔进去了

  • string转wstring / wstring转string
  • urlEncode / urlDecode
  • getTimeStamp
  • mergeCookies
  • findText

头文件(Network.h):

/* * Network.h * * Created on: 2017年1月19日 * Author: Junyi */
#include 
#include 
#include 
#include 
#include 
using namespace std;
class Network {
public:
    int getinmemory();

    vector<string> split(string str, string pattern);

    wstring string2wstring(const string str);
    string wstring2string(const wstring str);
    wstring findText(const wstring origin, const wstring find1, const wstring find2);
    string urlEncode(const string& str);
    string urlDecode(const string& str);
    time_t getTimeStamp();

    string mergeCookies(string cookies1, string cookies2);
    int get(const string url_, const string cookies_, string & cookiesRecv_, curl_slist * headers_, wstring & recvData_);
    int post(const string url_, const string postData_, const string cookies_, string & cookiesRecv, curl_slist * headers_, wstring & recvData_);

    Network();
    virtual ~Network();

private:
    struct MemoryStruct {
        char *memory;
        size_t size;
    };
    static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
    {
        size_t realsize = size * nmemb;
        struct MemoryStruct *mem = (struct MemoryStruct *)userp;

        mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
        if (mem->memory == NULL) {
            /* out of memory! */
            spsc_queue_for_debug.push("not enough memory (realloc returned NULL)\n");
            return 0;
        }

        memcpy(&(mem->memory[mem->size]), contents, realsize);
        mem->size += realsize;
        mem->memory[mem->size] = 0;

        return realsize;
    }
};

实现(Network.cpp)

/* * Network.cpp * * Created on: 2017年1月19日 * Author: Junyi */

#include 
#include 
#include 
#include 

#include 

#include 
#include 

#include "Network.h"

using namespace std;

namespace patch
{
    template < typename T > std::string to_string( const T& n )
    {
        std::ostringstream stm ;
        stm << n ;
        return stm.str() ;
    }
}
unsigned char toHex(unsigned char x)
{
    return  x > 9 ? x + 55 : x + 48;
}

unsigned char fromHex(unsigned char x)
{
    unsigned char y;
    if (x >= 'A' && x <= 'Z') y = x - 'A' + 10;
    else if (x >= 'a' && x <= 'z') y = x - 'a' + 10;
    else if (x >= '0' && x <= '9') y = x - '0';
    else assert(0);
    return y;
}

time_t Network::getTimeStamp()
{//获取10位的时间戳
    time_t t = time(0);  // t is an integer type
    return t;
}

string Network::urlEncode(const string& str)
{
    std::string strTemp = "";
    size_t length = str.length();
    for (size_t i = 0; i < length; i++)
    {
        if (isalnum((unsigned char)str[i]) ||
            (str[i] == '-') ||
            (str[i] == '_') ||
            (str[i] == '.') ||
            (str[i] == '~'))
            strTemp += str[i];
        else if (str[i] == ' ')
            strTemp += "+";
        else
        {
            strTemp += '%';
            strTemp += toHex((unsigned char)str[i] >> 4);
            strTemp += toHex((unsigned char)str[i] % 16);
        }
    }
    return strTemp;
}
string Network::urlDecode(const string& str)
{
    std::string strTemp = "";
    size_t length = str.length();
    for (size_t i = 0; i < length; i++)
    {
        if (str[i] == '+') strTemp += ' ';
        else if (str[i] == '%')
        {
            assert(i + 2 < length);
            unsigned char high = fromHex((unsigned char)str[++i]);
            unsigned char low = fromHex((unsigned char)str[++i]);
            strTemp += high * 16 + low;
        }
        else strTemp += str[i];
    }
    return strTemp;
}
wstring Network::findText(const wstring origin, const wstring find1, const wstring find2)
{
    if (origin.empty())
        return L"";

    size_t found1, found2;
    found1 = origin.find(find1);
    if ((int)found1 == 0)
        return L"";
    found2 = origin.find(find2, found1);
    if ((int)found2 == 0)
        return L"";
    return origin.substr(found1 + find1.length(), found2 - found1 - find1.length());
}
// 需包含locale、string头文件、使用setlocale函数。
/*http://www.cnblogs.com/SunboyL/archive/2013/03/31/stringandwstring.html*/
wstring Network::string2wstring(const string str)
{// string转wstring
    unsigned len = str.size() * 2;// 预留字节数
    setlocale(LC_CTYPE, "");     //必须调用此函数
    wchar_t *p = new wchar_t[len];// 申请一段内存存放转换后的字符串
    mbstowcs(p, str.c_str(), len);// 转换
    wstring str1(p);
    delete[] p;// 释放申请的内存
    return str1;
}
string Network::wstring2string(const wstring str)
{// wstring转string
    unsigned len = str.size() * 4;
    setlocale(LC_CTYPE, "");
    char *p = new char[len];
    wcstombs(p, str.c_str(), len);
    string str1(p);
    delete[] p;
    return str1;
}
vector<string> Network::split(string str, string pattern)
{
    string::size_type pos;
    vector<string> result;
    str += pattern;//扩展字符串以方便操作
    unsigned int size = str.size();

    for (unsigned int i = 0; iif (pos < size)
        {
            string s = str.substr(i, pos - i);
            result.push_back(s);
            i = pos + pattern.size() - 1;
        }
    }
    return result;
}
int Network::post(const string url_, const string postData_, const string cookies_, string & cookiesRecv_, curl_slist * headers_, wstring & recvData_)
{
    CURL *curl_handle;
    CURLcode res;

    struct MemoryStruct chunk;

    chunk.memory = (char *)malloc(1);  /* will be grown as needed by the realloc above */
    chunk.size = 0;    /* no data at this point */

    curl_handle = curl_easy_init();
    if(curl_handle)
    {
        curl_easy_setopt(curl_handle, CURLOPT_URL, url_.c_str());
        curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
        curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, postData_.c_str());
        curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, "");/* Start Cookies Engine */
        curl_easy_setopt(curl_handle, CURLOPT_COOKIE, cookies_.c_str());
        curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers_);
        curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
        res = curl_easy_perform(curl_handle);
        if (res != CURLE_OK) {
            curl_easy_cleanup(curl_handle);
            free(chunk.memory);
            return -1;
        }
        else
        {
            string cookiesResult("");
            struct curl_slist *cookiesList = NULL;
            struct curl_slist *cookiesList_original = NULL; // 保存一个指针副本
            curl_easy_getinfo(curl_handle, CURLINFO_COOKIELIST, &cookiesList);
            while(cookiesList)
            {
                vector<string> s = split(cookiesList->data, "\t");
                if(s.size() == 7)
                {
                    cookiesResult.append(s[5]);
                    cookiesResult.append("=");
                    cookiesResult.append(s[6]);
                    cookiesResult.append("; ");
                }
                cookiesList = cookiesList->next;
            }
            curl_slist_free_all(cookiesList_original); // 注意!!一定要释放 cookiesList_original !不然会引起内存泄漏

            cookiesResult = cookiesResult.substr(0, cookiesResult.size() - 2);
            cookiesRecv_ = cookiesResult;

            string afterCoding("");
            afterCoding = chunk.memory;
            afterCoding = boost::locale::conv::from_utf(afterCoding, "GBK");

            recvData_ = string2wstring(afterCoding);
        }

        curl_easy_cleanup(curl_handle);
        free(chunk.memory);
        return 0;
    }

    curl_easy_cleanup(curl_handle);
    free(chunk.memory);
    return -2;
}
int Network::get(const string url_, const string cookies_, string & cookiesRecv_, curl_slist * headers_, wstring & recvData_)
{
    CURL *curl_handle;
    CURLcode res;

    struct MemoryStruct chunk;

    chunk.memory = (char *)malloc(1);  /* will be grown as needed by the realloc above */
    chunk.size = 0;    /* no data at this point */
    /* init the curl session */
    curl_handle = curl_easy_init();
    if(curl_handle)
    {
        curl_easy_setopt(curl_handle, CURLOPT_URL, url_.c_str());
        curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, "");/* Start Cookies Engine */
        curl_easy_setopt(curl_handle, CURLOPT_COOKIE, cookies_.c_str());
        curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers_);
        curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, false);
        curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
        res = curl_easy_perform(curl_handle);
        if (res != CURLE_OK) {
            curl_easy_cleanup(curl_handle);
            free(chunk.memory);
            return -1;
        }
        else
        {
            string cookiesResult("");
            struct curl_slist *cookiesList = NULL;
            struct curl_slist *cookiesList_original = NULL;
            curl_easy_getinfo(curl_handle, CURLINFO_COOKIELIST, &cookiesList);
            cookiesList_original = cookiesList;
            while(cookiesList)
            {
                vector<string> s = split(cookiesList->data, "\t");
                if(s.size() == 7)
                {
                    cookiesResult.append(s[5]);
                    cookiesResult.append("=");
                    cookiesResult.append(s[6]);
                    cookiesResult.append("; ");
                }
                cookiesList = cookiesList->next;
            }
            curl_slist_free_all(cookiesList_original); // 注意!!一定要释放!不然会引起内存泄漏

            cookiesResult = cookiesResult.substr(0, cookiesResult.size() - 2);
            cookiesRecv_ = cookiesResult;

            string afterCoding("");
            afterCoding = chunk.memory;
            afterCoding = boost::locale::conv::from_utf(afterCoding, "GBK");

            recvData_ = string2wstring(afterCoding);
        }
        curl_easy_cleanup(curl_handle);
        free(chunk.memory);
        return 0;
    }
    curl_easy_cleanup(curl_handle);
    free(chunk.memory);
    return -2;
}

void mapInsert(map<string, string> &m, string first, string second)
{
    map<string, string>::iterator it;
    it = m.find(first);
    if (it == m.end())
        m.insert(pair<string, string>(first, second));
    else
        it->second = second;
}

string Network::mergeCookies(string cookies1, string cookies2)
{
    using namespace boost;
    map<string, string> m;//result cookies
    erase_all(cookies1, " ");
    erase_all(cookies2, " ");
    vector<string> s1 = split(cookies1, ";");
    vector<string> s2 = split(cookies2, ";");
    for (vector<string>::iterator it = s1.begin(); it != s1.end(); it++)
    {
        vector<string> s11 = split((*it), "=");
        if (s11.size() != 2)
            continue;
        mapInsert(m, s11[0], s11[1]);
    }
    for (vector<string>::iterator it = s2.begin(); it != s2.end(); it++)
    {
        vector<string> s22 = split((*it), "=");
        if (s22.size() != 2)
            continue;
        mapInsert(m, s22[0], s22[1]);
    }
    string result("");
    for (map<string, string>::iterator it = m.begin(); it != m.end(); it++)
    {
        result.append(it->first);
        result.append("=");
        result.append(it->second);
        result.append("; ");
    }
    result = result.substr(0, result.size() - 2);//去掉最后多余的的 [; ]
    return result;
}

Network::Network() {
}

Network::~Network() {
}

样例(main.cpp)

#include 
#include "Network.h"
int main()
{
    Network nt;
    string cookiesRecv("");
    wstring getRecv(L"");
    curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36");
    headers = curl_slist_append(headers, "Accept: application/json, text/javascript, */*; q=0.01");
    headers = curl_slist_append(headers, "Connection: Keep-Alive");
    headers = curl_slist_append(headers, "Pragma: no-cache");
    headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded; charset=UTF-8");

    nt.get("http://www.baidu.com", "", cookiesRecv, headers, getRecv);
    curl_slist_free_all(headers); // 用完就释放!

    std::cout << nt.wstring2string(getRecv) << std::endl;

    return 0;
}

编译:

g++ main.cpp Network.cpp Network.h -o main -lcurl -lcurldll -lboost_locale-mgw53-mt-1_62

(注意:-lcurldll 和 -lboost_locale-mgw53-mt-1_62 根据个人情况而定!
(linux下如果安装了 libcurl4-openssl-dev 和 libboost-dev,编译命令为:g++ main.cpp Network.cpp Network.h -o main -lcurl -lboost_locale
(编译环境:MinGW gcc-5.3.0 在各种库都配置正常的情况下,本篇文章编译通过并能正常使用)
附言:
C++新人一个,如代码有问题欢迎评论指出!

你可能感兴趣的:(C++学习)