最近在做团购酒店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. Css 使div标签下沉到页面最低部

    .footer{ position:fixed; bottom:0; } 使用这两个标签就能达到效果

  2. poj2407---欧拉函数应用

    欧拉函数介绍: 在数论中,对正整数n,欧拉函数是少于或等于n你的数中与n互质的数的数目. 通式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),其中 ...

  3. 常用笔记: 与VBS当中的Mid()类似的substr()小记

    VBS当中有Mid函数,一般形式为:Mid(str,start,len)   对应于JS就类似于:str.substr(start,len) 不过区别的是:VBS中start从1开始,而JS从0开始. ...

  4. 利用Comparator排序

    import java.util.Comparator; class Studentxx {     private String nameString;     private int age;   ...

  5. php数组使用技巧及操作总结

    数组,可以说是PHP的数据应用中较重要的一种方式.PHP的数组函数众多,下面是一些小结,借此记之,便于以后鉴之. 1. 数组定义 数组的定义使用 array()方式定义,可以定义空数组:<?ph ...

  6. Python2.7.3 学习——第一个程序 Hello Python World

    Hello World 每学一门语言开始的第一程序都是Hello World ,当然了Python也不例外,下面开始我们的Python第一个程序编写: 1,命令行: (1)打开终端,输入python, ...

  7. Chrome设计文档-多进程架构

    chromium multi-process architecture 本文档从high-level的角度描述Chromium的多进程架构. 问题 要构建一个决不崩溃或挂起的渲染引擎几乎是不可能的.同 ...

  8. MySQL 表分区的几种方法和注意

    分区方法1:Hash分区 例子: create table thash(x int ,y int) partition by hash(x) partitions 4; 就这么一句话表就分好区了.下一 ...

  9. Python GUI编程各种实现的对比

    Python GUI编程各种实现的对比 从 Python 语言的诞生之日起,就有许多优秀的 GUI 工具集整合到 Python 当中,这些优秀的 GUI 工具集,使得 Python 也可以在图形界面编 ...

  10. iOS6与iOS7屏幕适配技巧

    一.没有包装任何 导航控制器 或者 UITabBarController 1.控制器的view是UIScrollView\UITableView\UICollectionView时(控制器是UITab ...