libcurl 使用的几个注意事项
注:libcurl 入门指南( the tutorial ): http://curl.haxx.se/libcurl/c/libcurl-tutorial.html
0. 为使用的curl url 加入确定的协议头
原文:
If you specify URL without protocol:// prefix, curl will attempt to guess what protocol you might want. It will then default to HTTP but try other protocols based on often-used host name prefixes. For example, for host names starting with "ftp." curl will assume
you want to speak FTP.
1. 把 curl_easy_perform() 回调数据直接写到文件里(FILE *)
原文:
libcurl offers its own default internal callback that will take care of the data if you don't set the callback with CURLOPT_WRITEFUNCTION. It will then simply output the received data to stdout. You can have the default callback write the data to a different
file handle by passing a 'FILE *' to a file opened for writing with the CURLOPT_WRITEDATA option.
源代码中的实现:
这样,就能够少写一个回调函数了(喂,你是有多懒啊),示比例如以下
FILE *fp;
fp = fopen("/root/test.bmp", "wb");
...
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
...
fclose(fp);
2. curl_easy_perform 返回值处理
使用 CURLOPT_ERRORBUFFER 保存错误, buf_size=CURL_ERROR_SIZE
或使用 curl_easy_strerror(res) (感觉这个简便)
演示样例:
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
{
printf("%s curl_easy_perform() error! \n", __FUNCTION__);
printf("error msg = %s\n", curl_easy_strerror(res));
curl_easy_cleanup(curl);
return -1;
}
3. 多线程环境配置 CURLOPT_NOSIGNAL
原文:
When using multiple threads you should set the CURLOPT_NOSIGNAL option to 1 for all handles. Everything will or might work fine except that timeouts are not honored during the DNS lookup - which you can work around by building libcurl with c-ares support. c-ares
is a library that provides asynchronous name resolves. On some platforms, libcurl simply will not function properly multi-threaded unless this option is set.
对于 CURLOPT_TIMEOUT(默认0), CURLOPT_CONNECTTIMEOUT(默认300)选项:
In unix-like systems, this might cause signals to be used unless CURLOPT_NOSIGNAL is set.
4. 设置 CURLOPT_VERBOSE、CURLOPT_HEADER 的必要性
原文:
There's one golden rule when these things occur: set the CURLOPT_VERBOSE option to 1. It'll cause the library to spew out the entire protocol details it sends, some internal info and some received protocol data as well (especially when using FTP). If you're
using HTTP, adding the headers in the received output to study is also a clever way to get a better understanding why the server behaves the way it does. Include headers in the normal body output with CURLOPT_HEADER set 1.
经试验:
设置 curl_easy_setopt(curl, CURLOPT_HEADER, 1L) 后,回调函数会返回 http头相关信息(原本是直接输出到stdout的)。考虑到还要过滤这些信息,所以还是不要设置这个了
5. curl post 注意事项
原文:
Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header. You can disable this header with CURLOPT_HTTPHEADER as usual.
解释:
当使用libcurl的POST方式时,假设POST数据的大小大于1024个字节,libcurl不会直接发送POST请求,而是会分为两步运行请求:
<1> 发送一个请求,该请求头部包括一个Expect: 100-continue的字段,用来询问server是否愿意接受数据
<2> 当接收到从server返回的100-continue的应答后,它才会真正的发起POST请求。将数据发送给server。
对于“100-continue"这个字段,RFC文档(http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3)是这么解释的:
它能够让client在发送请求数据之前去推断server是否愿意接收该数据。假设server愿意接收,client才会真正发送数据,
这么做的原因是假设client直接发送请求数据,可是server又将该请求拒绝的话。这样的行为将带来非常大的资源开销。
所以为了避免这样的情况,libcurl在发送大于1024字节的POST请求时採用了这样的方法,可是相对的,它会引起请求延迟的加大,
另外并非全部的server都会正确处理而且应答”100-continue“,比方lighttpd,就会返回417”Expectation Failed“,造成请求逻辑出错。
解决的方法:
// POST数据的大于1024个字节
struct curl_slist *headerlist = NULL;
static const char buf[] = "Expect:";
headerlist = curl_slist_append(headerlist, buf); /* initalize custom header list */
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); /* set header*/
curl_slist_free_all(headerlist); /* free slist */
6. 回调函数的正确返回
return (size * nmemb);
原因:
Your callback function should return the number of bytes it "took care of". If that is not the exact same amount of bytes that was passed to it, libcurl will abort the operation and return with an error code.
假设回调函数中接收的数据有误,个人感觉能够返回0或者返回你已经处理的数据数。
由于源代码的处理例如以下:
/* If the previous block of data ended with CR and this block of data is
just a NL, then the length might be zero */
// len 为要发送给回调函数的数据长度
if(len) {
wrote = data->set.fwrite_func(ptr, 1, len, data->set.out);
}
else {
wrote = len;
}
if(wrote != len) {
failf(data, "Failed writing body (%zu != %zu)", wrote, len);
return CURLE_WRITE_ERROR;
}
libcurl 使用的几个注意事项的更多相关文章
- libcurl 多线程使用注意事项 - Balder~专栏 - 博客频道 - CSDN.NET
libcurl 多线程使用注意事项 - Balder~专栏 - 博客频道 - CSDN.NET libcurl 多线程使用注意事项 分类: C/C++学习 2012-05-24 18:48 2843人 ...
- Linux libcurl安装及注意事项
一.下载 官网下载地址 : https://curl.haxx.se/download.html 选择最新的一个即可. 二.安装 1.解压 下载到的压缩包为curl-7.51.0.tar.gz,使用 ...
- linux信号处理及libcurl的坑
前言: 最近有个项目, 需要访问第三方服务. 该服务是通过http的形式访问的, 为了安全和加密, 对方提供了一个加密用的C/C++库, 用于对参数进行处理. 鉴于此, 选用了C/C++语言 ...
- 【转载】linux信号处理及libcurl的坑
转载自http://www.cnblogs.com/mumuxinfei/p/4363466.html 前言: 最近有个项目, 需要访问第三方服务. 该服务是通过http的形式访问的, 为了安 ...
- libcurl get post http
一. 概念 1. 为什么要使用libcurl 1) 作为http的客户端,可以直接用socket连接服务器,然后对到的数据进行http解析,但要 ...
- qt5集成libcurl实现tftp和ftp的方法一:搭建环境(五篇文章)
最近使用QT5做一个软件,要求实现tftp和ftp文件传输,使用QT5开发好UI界面等功能,突然发现QT5不直接提供tftp和ftp支持,无奈之下只好找第三方库来间接实现,根据网友的介绍,libcur ...
- 最全的libcurl库资源整理
C++ 用libcurl库进行http 网络通讯编程 百度登陆协议分析!!!用libcurl来模拟百度登陆 C++使用libcurl做HttpClient 使用libcurl库进行HTTP的下载 li ...
- (转)libcurl库使用方法,好长,好详细。
一.ibcurl作为是一个多协议的便于客户端使用的URL传输库,基于C语言,提供C语言的API接口,支持DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP ...
- c++利用jsoncpp libcurl 构造http 包(原)
我们手游要接入uc九游进行测试,要用http向uc那边的sdk 服务器post json数据. 虽然他们提供了php,java还有c#的服务端demo,但是我们服务器是C++写的,我实在不想中间再转 ...
随机推荐
- 自定义流程gooflow.08 demo在线演示
一.功能简介 gooflow功能清单1.自定义流程绘制2.自定义属性添加3.支持3种步骤类型 普通审批步骤 自动决策步骤 手动决策步骤 4.决策方式(支持js决策,sql语句决策) 5.审批人员参与方 ...
- Android ART简介
一. Android ART简介 Android DEX/ODEX/OAT文件
- wpf数据自动树结构
在项目中,时常会遇到存在上下级关系的数据.在呈现方面,按照传统方法,不得不组装TreeNode之后添加到TreeView 中,已实现树形数据的显示.如果项目中需要多处使用树,毫无疑问这将存在巨大的代码 ...
- RegularExpressionValidator 常用
RegularExpressionValidator 控件用于验证输入值是否匹配正则表达式指定的模式 属性: ControlToValidate="要验证的控件名称" Valida ...
- VS 调试相关
最近用VS2013 调试遇到的一点小问题,老年痴呆做一下记录. 1. IIS 用 w3wp.exe 调试: IIS 中的文件系统与工程的保持一致,否则断点不会命中: 发布文件系统后,重启站点对应的应用 ...
- Linux网络编程-----Socket地址API
(1) 通用socket地址 socket网络编程接口中表示socket地址的是结构体sockaddr,其定义如下: #include<bits/socket.h> struct sock ...
- 解决类型“System.Web.UI.UpdatePanel”不具有名为“Gridview”的公共属性,
类型“system.web.ui.updatepanel” 不具有名为“XXX”的公共属性,其实原因很简单.就是少了一个<ContentTemplate></ContentTempl ...
- Tomcat架构(二)
5.容器组件 这一小节中我们将讨论请求处理组件:引擎(engine).虚拟主机.上下文(context)组件. 5.1.引擎(engine) 引擎表示可运行的Catalina的servlet引擎实例并 ...
- Warm up 2
hdu4619:http://acm.hdu.edu.cn/showproblem.php?pid=4619 题意:题目大意:给你两种纸牌 ,一种水平放置共有n张 ,一种竖直放置共有m张.水平放置的纸 ...
- js页面传参数时,参数值包含特殊字符的处理
js页面传参数时,参数值包含特殊字符应该怎么处理,解决方法就是利用js的escape函数,这个函数在解决中文乱码等方面应用的比较广泛.推荐使用. 工作中遇到的小问题,一个页面中通过window.sho ...