[译]libcurl_tutorial
Handle the Easy libcurl
To use the easy interface, you must first create yourself an easy handle. You need one handle for each easy session you want to perform. Basically, you should use one handle for every thread you plan to use for transferring. You must never share the same handle in multiple threads.
要使用easy接口,需要先创建easy handle.
一个handle用于一个easy session中,基本上就是说每个需要使用curl的线程,都要有自己的easy handle。
同一个Handle不可用于多个线程中。
Get an easy handle with
easyhandle = curl_easy_init();
这样来获取一个easy handle
easyhandle = curl_easy_init();
It returns an easy handle. Using that you proceed to the next step: setting up your preferred actions. A handle is just a logic entity for the upcoming transfer or series of transfers.
curl_easy_init()返回一个easy handle,获得easy handle后再继续进行下一步操作,一个handle是一个逻辑的实体,用于
即将执行的一个或多个数据传输。
You set properties and options for this handle using curl_easy_setopt. They control how the subsequent transfer or transfers will be made. Options remain set in the handle until set again to something different. They are sticky. Multiple requests using the same handle will use the same options.
使用curl_easy_setopt设置Handle的属性和选项。
这些设置在之后的数据传输中生效,只要不修改这些属性和选项,他们将一直生效。
If you at any point would like to blank all previously set options for a single easy handle, you can call curl_easy_reset and you can also make a clone of an easy handle (with all its set options) using curl_easy_duphandle.
如果想要清空easy handle中的属性和选项,使用curl_easy_reset。
如果想要克隆一个easy handle,使用curl_easy_duphandle。(克隆会带上原有的所有属性和选项)
Many of the options you set in libcurl are "strings", pointers to data terminated with a zero byte. When you set strings with curl_easy_setopt, libcurl makes its own copy so that they don't need to be kept around in your application after being set[4].
libcurl中大多数选项都是string,以'\0'作为终止符。
使用curl_easy_setopt设置属性后,你不需要保存这个string,libcurl会复制string。
One of the most basic properties to set in the handle is the URL. You set your preferred URL to transfer with CURLOPT_URL in a manner similar to:
curl_easy_setopt(handle, CURLOPT_URL, "http://domain.com/");
handle最基础的属性设置就是设置URL,方法如下:
curl_easy_setopt(handle, CURLOPT_URL, "http://domain.com/");
Let's assume for a while that you want to receive data as the URL identifies a remote resource you want to get here. Since you write a sort of application that needs this transfer, I assume that you would like to get the data passed to you directly instead of simply getting it passed to stdout. So, you write your own function that matches this prototype:
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
我们假设你现在想要接收远程URL的数据,
当你写了一个简短的程序, 我假设你想要直接接收数据而不是输出到stdout。
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
You tell libcurl to pass all data to this function by issuing a function similar to this:
curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, write_data);
通过以下代码发送数据:
curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, write_data);
You can control what data your callback function gets in the fourth argument by setting another property:
curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, &internal_struct);
你可以使用回调参数控制数据,第四个参数是回调参数
curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, &internal_struct);
Using that property, you can easily pass local data between your application and the function that gets invoked by libcurl. libcurl itself won't touch the data you pass with CURLOPT_WRITEDATA.
使用这个属性,你可以轻松的传输本地数据,这个函数由libcurl唤醒。
libcurl本身不会修改CURLOPT_WRITEDATA属性的数据
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.
如果你没有使用CURLOPT_WRITEFUNCTION设置回调,libcurl提供默认的内部回调,他会直接将收到的数据输出到stdout。
你也可以使用CURLOPT_WRITEDATA,以及文件指针'FILE *',将数据写入到文件中。
Now, we need to take a step back and have a deep breath. Here's one of those rare platform-dependent nitpicks. Did you spot it? On some platforms[2], libcurl won't be able to operate on files opened by the program. Thus, if you use the default callback and pass in an open file with CURLOPT_WRITEDATA, it will crash. You should therefore avoid this to make your program run fine virtually everywhere.
在一些平台,libcurl不能操作通过程序打开的文件(在windows中,libcurl作为dll的情况下,不能这样操作)。
因此,如果你使用默认的回调,并使用CURLOPT_WRITEDATA传入一个已经打开的文件,会造成崩溃。
(CURLOPT_WRITEDATA was formerly known as CURLOPT_FILE. Both names still work and do the same thing).
CURLOPT_FILE是CURLOPT_WRITEDATA的前称,现在仍然可用,含义不变。
If you're using libcurl as a win32 DLL, you MUST use the CURLOPT_WRITEFUNCTION if you set CURLOPT_WRITEDATA - or you will experience crashes.
如果libcurl在win32下作为dll使用,并且设置了CURLOPT_WRITEDATA,你必须使用CURLOPT_WRITEFUNCTION,否则崩溃。
There are of course many more options you can set, and we'll get back to a few of them later. Let's instead continue to the actual transfer:
success = curl_easy_perform(easyhandle);
设置了这么多,我们先执行一下:
success = curl_easy_perform(easyhandle);
curl_easy_perform will connect to the remote site, do the necessary commands and receive the transfer. Whenever it receives data, it calls the callback function we previously set. The function may get one byte at a time, or it may get many kilobytes at once. libcurl delivers as much as possible as often as possible. 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.
curl_easy_perform会连接远程服务器,执行操作和接受数据。
当收到数据时,会调用之前设置的回调函数。
函数可能一次接受1字节,也能一次接受多个字节,不一定,libcurl会尽量的投递。
你的回调函数应该返回接受到的字节数。
如果传输的数据和预想中的不一致,libcurl会中断,并返回错误码。
When the transfer is complete, the function returns a return code that informs you if it succeeded in its mission or not. If a return code isn't enough for you, you can use the CURLOPT_ERRORBUFFER to point libcurl to a buffer of yours where it'll store a human readable error message as well.
当传输完成,函数会返回结果。
如果返回值不够用,可以使用CURLOPT_ERRORBUFFER获取错误原因字符串。
If you then want to transfer another file, the handle is ready to be used again. Mind you, it is even preferred that you re-use an existing handle if you intend to make another transfer. libcurl will then attempt to re-use the previous connection.
如果你想要传输其他文件,handle已经可以再次使用了,libcurl会重用handle
For some protocols, downloading a file can involve a complicated process of logging in, setting the transfer mode, changing the current directory and finally transferring the file data. libcurl takes care of all that complication for you. Given simply the URL to a file, libcurl will take care of all the details needed to get the file moved from one machine to another.
某些协议下载文件的过程可能比较复杂,例如登陆、设置传输模式、目录切换,最后才是传输数据。
libcurl会帮你处理这些复杂的流程。
Multi-threading Issues
多线程问题
The first basic rule is that you must never simultaneously share a libcurl handle (be it easy or multi or whatever) between multiple threads. Only use one handle in one thread at any time. You can pass the handles around among threads, but you must never use a single handle from more than one thread at any given time.
基本原则是不能在多线程中共享libcurl handle(easy 、multi什么的都不可以)。
一个handle同时只能在一个线程中使用。
你可以在线程间传递handle,但是不能同时使用。
libcurl is completely thread safe, except for two issues: signals and SSL/TLS handlers. Signals are used for timing out name resolves (during DNS lookup) - when built without using either the c-ares or threaded resolver backends.
libcurl是线程安全的,除了2个问题:
signals 和 SSL/TLS handle。
信号用于DNS lookup中。
If you are accessing HTTPS or FTPS URLs in a multi-threaded manner, you are then of course using the underlying SSL library multi-threaded and those libs might have their own requirements on this issue. Basically, you need to provide one or two functions to allow it to function properly. For all details, see this:
如果在多线程中访问HTTPS和FTPS的URL,肯定会用到SSL库
OpenSSL
http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION
GnuTLS
http://gnutls.org/manual/html_node/Thread-safety.html
NSS
is claimed to be thread-safe already without anything required.
PolarSSL
Required actions unknown.
yassl
Required actions unknown.
axTLS
Required actions unknown.
Secure Transport
The engine is fully thread-safe, and no additional steps are required.
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.
Also, note that CURLOPT_DNS_USE_GLOBAL_CACHE is not thread-safe.
[译]libcurl_tutorial的更多相关文章
- RxJS + Redux + React = Amazing!(译一)
今天,我将Youtube上的<RxJS + Redux + React = Amazing!>翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: https:/ ...
- Entity Framework 6 Recipes 2nd Edition 译 -> 目录 -持续更新
因为看了<Entity Framework 6 Recipes 2nd Edition>这本书前面8章的翻译,感谢china_fucan. 从第九章开始,我是边看边译的,没有通读,加之英语 ...
- RxJS + Redux + React = Amazing!(译二)
今天,我将Youtube上的<RxJS + Redux + React = Amazing!>的后半部分翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: ht ...
- 「译」JUnit 5 系列:条件测试
原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...
- CSharpGL(31)[译]OpenGL渲染管道那些事
CSharpGL(31)[译]OpenGL渲染管道那些事 +BIT祝威+悄悄在此留下版了个权的信息说: 开始 自认为对OpenGL的掌握到了一个小瓶颈,现在回头细细地捋一遍OpenGL渲染管道应当是一 ...
- [译]基于GPU的体渲染高级技术之raycasting算法
[译]基于GPU的体渲染高级技术之raycasting算法 PS:我决定翻译一下<Advanced Illumination Techniques for GPU-Based Volume Ra ...
- Entity Framework 6 Recipes 2nd Edition(9-4)译->Web API 的客户端实现修改跟踪
9-4. Web API 的客户端实现修改跟踪 问题 我们想通过客户端更新实体类,调用基于REST的Web API 服务实现把一个对象图的插入.删除和修改等数据库操作.此外, 我们想通过EF6的Cod ...
- Entity Framework 6 Recipes 2nd Edition(10-1)译->非Code Frist方式返回一个实体集合
存储过程 存储过程一直存在于任何一种关系型数据库中,如微软的SQL Server.存储过程是包含在数据库中的一些代码,通常为数据执行一些操作,它能为数据密集型计算提高性能,也能执行一些为业务逻辑. 当 ...
- 「译」JUnit 5 系列:扩展模型(Extension Model)
原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...
随机推荐
- codeforces Gym 100814 A、B、F、I
A题 先求出来这个数是第几大 阶乘求概率p 然后计算获得胜率的概率 常规解法把所有情况考虑一遍(跳1次,2次,3次……)要用到组合数 数可能太大了会爆的行不通 我们观察发现它有递推性质,从第二大 ...
- Codeforces Round #343 (Div. 2)【A,B水题】
A. Far Relative's Birthday Cake 题意: 求在同一行.同一列的巧克力对数. 分析: 水题~样例搞明白再下笔! 代码: #include<iostream> u ...
- 静态区间第k大(归并树)
POJ 2104为例 思想: 利用归并排序的思想: 建树过程和归并排序类似,每个数列都是子树序列的合并与排序. 查询过程,如果所查询区间完全包含在当前区间中,则直接返回当前区间内小于所求数的元素个数, ...
- POJ 3468_A Simple Problem with Integers(树状数组)
完全不知道该怎么用,看书稍微懂了点. 题意: 给定序列及操作,求区间和. 分析: 树状数组可以高效的求出连续一段元素之和或更新单个元素的值.但是无法高效的给某一个区间的所有元素同时加个值. 不能直接用 ...
- T1003 电话连线 codevs
http://codevs.cn/problem/1003/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 一个国家有n个城市 ...
- MongoDB小结25 - 复合唯一索引
只要满足索引的其中之一不同即可 db.blog.ensureIndex({"username":1,"blogname":1}) 作者和作品名其中之一不同即可创 ...
- 冲刺Offer - 二叉树的深度
https://www.nowcoder.net/practice/435fb86331474282a3499955f0a41e8b?tpId=13&tqId=11191&tPage= ...
- Windows Server2008 R2 设置NAT 让Hyper-V连接Internet
1.添加虚拟网卡,设置为内部,并且固定IP地址192.168.1.1 255.255.255.0 此为内网网卡 2.添加服务器角色:DHCP服务器,DNS服务器,网络策略和访问服务 3."网 ...
- Hadoop HDFS NFS GateWay部署深入具体解释
目的:通过挂载的方式,能够相似訪问本地磁盘的方式一样的訪问Hadoop文件.简单.方便.快捷. 0.系统版本号&hadoop版本号 1)系统版本号 [root@WEB-W031 sbin]# ...
- Office 连供打印机无法进纸怎么办 卡纸,塞纸怎么办
我昨天打印还好好的,今天无法进纸了,哪怕只放一张纸,也是左边进去一点点,然后就塞住了,吸不下去了. 因为你的打印机里面有异物.你把连供拆掉(当心墨水流出来,把墨盒拆掉之后放高一点并用纸巾包住,不要 ...