每天进步一点点:C++ 中使用libcurl 获取返回数据的学习
libcurl·@oflyhigh·
0.000 HBD每天进步一点点:C++ 中使用libcurl 获取返回数据的学习
最近使用学习在C++中使用libcurl,不得不感概PHP是世界上最好的语言,PHP用curl那叫一个省心。Python用起来就要略复杂了,详情可以看我之前的学习笔记[《每天进步一点点:Python中使用PycURL访问STEEM RPC》](https://steemit.com/pycurl/@oflyhigh/python-pycurl-steem-rpc)。不过嫌弃PycURL麻烦的可以换Requests等其它库。 但是C++使用libcurl 呢?哎,全是泪水。  (图源 :[pixabay](https://pixabay.com/)) # POST、GET 其实libcurl简单的POST、GET操作还是很简单的 可以参考以下链接: * [Very simple HTTP GET](https://curl.haxx.se/libcurl/c/simple.html) * [Very simple HTTP POST](https://curl.haxx.se/libcurl/c/simplepost.html) 以POST操作为例:  大致就是初始化、设置参数、执行、清理四个步骤。运行上述代码,我们也可以看到POST的返回内容。但是等等,内容是咋返回的呢? # libcurl 返回数据 #### 默认至stdout 为了找回数据是咋返回的,我搜索了一些文档,不过还是看的迷迷糊糊的,知道我看了这两个页面: * [CURLOPT_WRITEDATA explained](https://curl.haxx.se/libcurl/c/CURLOPT_WRITEDATA.html) * [CURLOPT_WRITEFUNCTION explained](https://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html) 其中CURLOPT_WRITEDATA的说明中提到: >By default, this is a FILE * to stdout. 也就是说数据默认输出到标准输出。这就解释了上述GET、POST示例中并没有使用cout、printf一类的输出操作,我们却可以看到内容。 #### 保存至变量 接下来的问题是,如何将我们要的输出数据保存到变量呢?一种方法是CURLOPT_WRITEDATA中的文件指针换成我们自己的文件,然后输出到文件,(再读回来),如果是下载文件等操作,这种方法还是很便利的。但是如果我们需要在程序中处理数据呢?再读回来的操作显然很傻。 答案是使用`CURLOPT_WRITEFUNCTION`以及`CURLOPT_WRITEDATA`,当我们设置了`CURLOPT_WRITEFUNCTION`,每次我们收到数据后,这个回调函数将会被调用。 >`size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);` >`CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEFUNCTION, write_callback);` 其中`ptr`是我们收到数据的指针,数据长度为`size*nmemb`,`userdata`是由`CURLOPT_WRITEDATA`设置的变量,操作方式如下: >`CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEDATA, void *pointer);` 使用`CURLOPT_WRITEFUNCTION`需要注意以下几点: * 回调函数**可能被调用不止一次**,换句话将数据可能不是一次性返回的 * 每次返回的数据长度为:**`size*nmemb`** * 回调函数需要返回接收数据的长度,否则会引发**`CURLE_WRITE_ERROR`** ***我在这三点上都栽过跟头***,希望大家注意别犯和我一样的错误。 # 保存到变量的例子 libcurl的例子页面,提供了一个[将返回数据保存到变量的例子](https://curl.haxx.se/libcurl/c/getinmemory.html) >Shows how the write callback function can be used to download data into a chunk of memory instead of storing it in a file. 例子中定义一个包含指向内存的指针变量,以及接受到的数据长度的变量,然后使用molloc以及realloc以及memcpy来操作内存。这样每次回调函数被调用就会自动计算需要的内存,动态分配,然后复制数据。 这个例子使用了C语言的一些手法来达成这个目的,相对而言比较复杂,需要我们自己管理以及释放内存等。对于文本数据而言,使用string还是超方便的,这里就不再赘述了。 # 参考链接 * [Very simple HTTP GET](https://curl.haxx.se/libcurl/c/simple.html) * [Very simple HTTP POST](https://curl.haxx.se/libcurl/c/simplepost.html) * [CURLOPT_WRITEDATA explained](https://curl.haxx.se/libcurl/c/CURLOPT_WRITEDATA.html) * [CURLOPT_WRITEFUNCTION explained](https://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html) * [getinmemory](https://curl.haxx.se/libcurl/c/getinmemory.html) * [每天进步一点点:Python中使用PycURL访问STEEM RPC](https://steemit.com/pycurl/@oflyhigh/python-pycurl-steem-rpc)
👍 oflyhigh, liangfengyouren, hepeng.chn, bambugrove, novelafans, garryliew, eval, ebusiness, fadyhero, auntigormint, ms8988, damarth, abraomarcos, ikonik, lemminon, xiaoyuanwmm, mibnu, technologynepal, wylo, amponchiek, mycat, abss, steemtruth, peterschilder, bobdos, lebin, canbethisone, jackhircus, aabb, cryptohustler, juspa, exec, yulan, mark-waser, digital-wisdom, yyyy, jwaser, herpetologyguy, bwaser, ellepdub, ethical-ai, strong-ai, davidjkelley, technoprogressiv, handyman, deanliu, profitgenerator, davidke20, winniex, sanzo, khalilad, rebecca80, sweethoney, bearpaw, stakuza, razor80, mrliga, freedom-fighter, chaerin, cryptoknight27, raku, speeding, xiaohui, abetterworld, chann, weavingwords, heyeshuang, annabellenoelle, janiceting, coindzs, jiangchen, laoyao, yumisee, joeliew, iipoh06, ethansteem, khayziljoy, windrockswater, xiaokongcom, lalala, raili, fastiduos, mrtv2, midnightoil, saury, nanosesame, jkkim, lingfei, dragon40, kingofdew, chinadaily, blackbunny, shirlam, cnbuddy, devilwsy, helene, rosatravels, marram, blockchainbilly, redes, ebejammin, somebody, ethanlee, emcvay, austinsandersco, ewq, mandagoi, jianghao, maiyude, fishbb, historylover, chessmasterhex, fanso, walkinharmony, ripperone, lancy, lydiachan, asterix87, that1consultant, resteeming, davaowhenyo, allenshayzar, ravenousappetite, nitro.live, vfxness, valleybkk, bdmusa, artsaboutit, hmayak, victory622, sj666, fundurian, ety001, enareest, idx, abit, bxt, dodybireuen, ace108, adm, englishtchrivy, pharesim, hussein.elnoby,