libcurl的使用问题“Expect100-continue”

最近在做团购酒店APP分享到qzone功能,使用libcurl访问qzone的分享cgi接口,酒店分享信息以POST方式传输,在测试的时候发现分享接口平均有2s的延迟,这延迟也太大了吧,于是乎问了空间的接口人,答曰:怎么可能,这个接口的平均调用时延是100-200ms,肯定是你的代码有问题。好吧,开始检查代码,使用strace -p跟踪系统调用,发现curl发送了两次请求,其中第一次请求的响应特别的慢,额,原来这个才是导致延迟的罪魁祸首,tcpdump之后发现curl发送的第一个请求包含一个Expect: 100-continue的头,这是为什么呢,于是开始百度,google,得到的解释如下:

当使用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)是这么解释的:它可以让客户端在发送请求数据之前去判断服务器是否愿意接收该数据,如果服务器愿意接收,客户端才会真正发送数据,这么做的原因是如果客户端直接发送请求数据,但是服务器又将该请求拒绝的话,这种行为将带来很大的资源开销。所以为了避免这种情况,libcurl在发送大于1024字节的POST请求时采用了这种方法,但是相对的,它会引起请求延迟的加大,另外并不是所有的server都会正确处理并且应答”100-continue“,比如lighttpd,就会返回417”Expectation Failed“,造成请求逻辑出错。

如果确定服务器不会拒绝1024个字节以上的POST请求,就可以不使用该方法而且也可以避免以上提到的两个副作用,解决的办法如下:

[cpp] view plaincopy

  1. // disable Expection header
  2. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, array(‘Expect:‘));

禁用该机制后,测试了一下qzone分享接口平均调用时延减小到了200ms,这才是正常的延时嘛,嘿嘿。
参考资料:
http://www.laruence.com/2011/01/20/1840.html

from:http://blog.csdn.net/zxgfa/article/details/7604624

时间: 2024-10-06 00:46:49

libcurl的使用问题“Expect100-continue”的相关文章

libcurl实现解析(3) - libcurl对select的使用

1.前言 在本系列的前一篇文章中,介绍了libcurl对poll()的使用.参考"libcurl原理解析(2) - libcurl对poll的使用". 本篇文章主要分析curl_poll()中对select()的封装使用.与前一篇类似,我们只分离出与select相关的代码. 2.curl_poll函数分析 这个函数中使用到的一些其它的数据结构,可以参考前一篇文章中的介绍.本篇不再介绍. /* 这个函数是对poll()的封装.如果poll()不存在,则使用select()替代. 如果使用

MinGW64 how-to(内含编译openssl,libjpeg,libcurl等例子)

Index of contents Setting up the MinGW 64 environment Step 1) building libiconv Step 2) building libz Step 3) building libjpeg Step 4) building libpng Step 5) building libtiff Step 6) building libproj Step 7) building libgeotiff Step 8) building libg

boost::asio 使用 libcurl

curl 使用 asio 的官方样例 http://curl.haxx.se/libcurl/c/asiohiper.html, 但这个例子用起来有很明细的 bug,asio 异步IO 只注册一次,也就是第一次 aync_read 之后对socket的读都是由 超时 驱动的.自己把样例改了下. curl 和 asio 组合的时候相比(select, libevent, libuv)非常复杂.绝不仅仅是多了下面2个 socket 创建和关闭的回调函数. CURLOPT_OPENSOCKETFUNC

libcurl原理解析(2) - libcurl对poll的使用

libcurl同时封装了select以及poll这两种I/O机制.代码中使用宏HAVE_POLL_FINE对这两者进行分离.如果定义了这个宏,则使用poll,否则使用select. 这两者的使用代码都定义在函数curl_poll()中,而函数定义在文件lib/select.c中.为了方便分析,阅读,会将select与poll相关的代码分离开来,各自独立分析. 本篇文章主要分析curl_poll()中对poll的封装使用. 先看下使用到的一些数据结构的定义: typedef int curl_so

libCurl的文件上传

最近在需要使用curl的上传功能,使用libCurl来实现.因此,先使用curl命令操作,然后再使用libCurl实现. 基于Http协议的文件上传的标准方法是: 基于POST Form的文件上传  RFC1867. 这个方法使用非常广泛,这个RFC规定了FORM上传文件的标准方法,如下介绍了基于libcurl来开发upload功能. 开发实现过程 1. 使用curl 命令行执行代码,  2. 跟踪分析 curl的request和response, 3.使用libCurl的API进行开发实现 0

while与do while 区别 for循环的简介及break和continue的区别

do while 循环和while循环的区别   1.do while循环是先执行循环体,然后判断循环条件,如果为真,则执行下一步循环,否则终止循环:    while循环是先判断循环条件,如果条件为真则执行循环体:   2.do while循环条件后面必须有一个分号,这个分号表明循环结束. 1.for循环 for循环是更加简洁的循环语句,大部分情况下,for循环可以代替while循环.do-while循环. for循环的格式为: for( 初始语句  ; 执行条件  ; 增量 ) { 循环体

跳转控制语句continue

1 continue的使用场景: 1.1 在循环语句中 注意:离开使用场景的存在是没有意义的 2 continue的作用: 2.1 单层循环对比break,然后总结两者的区别 2.1.1 break 退出当前循环 public class BreakDemo { public static void main(String[] args) { for(int i = 0; i < 10; i++) { if (i == 2) { break;//跳出内层循环 } System.out.print

第五节:python continue break的用法

for i in range(1,100):   if i==50:     print 'i have print 50'     continue  print i 此处的print i 和 if i==50:属于同级,执行的都是上级for.  print 'i have print 50' 和continue属于同级. continue 为跳出本次循环,break为跳出整个循环.两者只能在循环中使用.

shell编程中for,while,util,case,select,break, continue用法详解

关于shell脚本的更多详细实例讲解请参考:http://www.cnblogs.com/yuexiaxiaoxi/category/646749.html Shell编程中循环命令用于特定条件下决定某些语句重复执行的控制方式,有三种常用的循环语句:for.while和until.while循环和for循环属于"当型循环",而until属于"直到型循环".循环控制符:break和continue控制流程转向. 参考:<Linux 与unix shell 编程指

Break、Continue、Return区别

1)break     直接跳出当前的循环,从当前循环外面开始执行,忽略循环体中任何其他语句和循环条件测试.他只能跳出一层循环,如果你的循环是嵌套循环,那么你需要按照你嵌套的层次,逐步使用break来跳出.     2)continue     也是终止当前的循环过程,但他并不跳出循环,而是继续往下判断循环条件执行语句.他只能结束循环中的一次过程,但不能终止循环继续进行. 3)return 语句可被用来使 正在执行分支程序返回到调用它方法.