每天进步一点点:C++ 中使用libcurl 获取返回数据的学习

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@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 呢?哎,全是泪水。

![](https://steemitimages.com/DQmRkLq6rRew3mHfx4vYGWyqpC8wSebLPeC2iZCXAdpuGkR/image.png)
(图源 :[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操作为例:
![](https://steemitimages.com/DQmPpAACUvZw8pGzaVmw6eP4JgHRA19kwo76S4oz4YyomsS/image.png)

大致就是初始化、设置参数、执行、清理四个步骤。运行上述代码,我们也可以看到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)
👍 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,