最近在做团购酒店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请求,就可以不使用该方法而且也可以避免以上提到的两个副作用,解决的办法如下:

  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

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

  1. boost::asio 使用 libcurl

    curl 使用 asio 的官方样例 http://curl.haxx.se/libcurl/c/asiohiper.html, 但这个例子用起来有很明细的 bug,asio 异步IO 只注册一次,也 ...

  2. libCurl的文件上传

    最近在需要使用curl的上传功能,使用libCurl来实现.因此,先使用curl命令操作,然后再使用libCurl实现. 基于Http协议的文件上传的标准方法是: 基于POST Form的文件上传  ...

  3. 使用libcurl的正确姿势

    libcurl支持访问http.ftp等各种服务器,下载图片AV什么的不在话下.但其存在多种接口,异步接口也很难以理解,到底什么样的使用姿势才是正确滴?我们来看看可用的体位: easy interfa ...

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

    1.前言 在本系列的前一篇文章中.介绍了libcurl对poll()的使用. 參考"libcurl原理解析(2) - libcurl对poll的使用". 本篇文章主要分析curl_ ...

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

    Index of contents Setting up the MinGW 64 environment Step 1) building libiconv Step 2) building lib ...

  6. 基于libcurl的restfull接口 post posts get gets

    头文件 #pragma once #ifndef __HTTP_CURL_H__ #define __HTTP_CURL_H__ #include <string> #include &q ...

  7. continue break 区别

    在循环中有两种循环方式 continue , break continue 只是跳出本次循环, 不在继续往下走, 还是开始下一次循环 break  将会跳出整个循环, 此循环将会被终止 count = ...

  8. 《Note --- Unreal --- MemPro (CONTINUE... ...)》

    Mem pro 是一个主要集成内存泄露检测的工具,其具有自身的源码和GUI,在GUI中利用"Launch" button进行加载自己待检测的application,目前支持的平台为 ...

  9. 《Note --- Unreal 4 --- Sample analyze --- StrategyGame(continue...)》

    ---------------------------------------------------------------------------------------------------- ...

  10. (转)利用libcurl和国内著名的两个物联网云端通讯的例程, ubuntu和openwrt下调试成功(四)

    1. libcurl 的参考文档如下 CURLOPT_HEADERFUNCTION Pass a pointer to a function that matches the following pr ...

随机推荐

  1. JavaSE思维导图(三)

  2. SGU 101.Domino( 欧拉路径 )

    求欧拉路径...直接dfs即可,时间复杂度O(N) -------------------------------------------------------------------------- ...

  3. 我使用过的Linux命令

    我使用过的Linux命令之tee - 重定向输出到多个文件 用途说明 在执行Linux命令时,我们可以把输出重定向到文件中,比如 ls >a.txt,这时我们就不能看到输出了,如果我们既想把输出 ...

  4. [ 转 ]jquery的ajax和getJson跨域获取json数据

    目前浏览器端跨域访问常用的两种方法有两种: 1.通过jQuery的ajax进行跨域,这其实是采用的jsonp的方式来实现的. jsonp是英文json with padding的缩写.它允许在服务器端 ...

  5. SQL 简单练习

    USE study; SELECT * FROM EMP --查询雇员姓名的最后三个字母 ) FROM EMP ; --查询10部门雇员进入公司的星期数 --1 查询部门30中的所有员工 --2 列出 ...

  6. latex如何把目录页的页码去掉?

    页眉的显示与关闭,清空,还有样式之间的切换,需要用到如下几个命令: \pagestyle  用于设置当前页以及后续页面的页眉显示情况(可称为页版式).中间页版式可由\thispagestyle命令来指 ...

  7. poj 3270 置换

    poj 置换的应用 黑书原题P248 /** 题意: 给定序列, 将其按升序排列, 每次交换的代价是两个数之和, 问代价最小是多少 思路:1.对于同一个循环节之内的,肯定是最小的与别的交换代价最小 2 ...

  8. iOS 开发技巧

    快速移除键盘 之前一直是讲view的父类改成control,然后加一个全屏按钮,点击让键盘消失.这个方法要写好多代码,现在一个比较好的方法是重写一个下面的方法: - (void)touchesBega ...

  9. SQL Server 数据库所有者

    1. 数据库所有者应当永远是 sa 用户 2. 改变数据库的所有者 alter authorization on database :: databaseName to sa; -- 这一句话把数据库 ...

  10. CCNP路由实验(4) -- BGP

    基本配置:enableconf tno ip do loenable pass ciscoline con 0logg syncexec-t 0 0line vty 0 4pass ciscologg ...