libcurl教程
- 格式:doc
- 大小:520.00 KB
- 文档页数:25
libcurl 源码编译Libcurl是一个开源的网络传输库,它支持多种协议,包括HTTP、FTP、SMTP等。
它的源码可以在官方网站上下载,也可以通过Git 仓库获取。
本文将介绍如何从源码编译libcurl。
我们需要下载libcurl的源码。
可以在官方网站上下载最新版本的源码,也可以通过Git仓库获取最新的开发版本。
下载完成后,我们需要解压源码包。
接下来,我们需要进入源码目录,执行configure脚本。
这个脚本会检查系统环境,生成Makefile文件。
在执行configure脚本时,可以指定一些选项,例如指定安装目录、指定编译器等。
例如,我们可以执行以下命令:./configure --prefix=/usr/local/libcurl --with-ssl这个命令指定了安装目录为/usr/local/libcurl,同时启用了SSL支持。
执行configure脚本后,会生成Makefile文件。
我们可以执行make命令来编译libcurl。
如果系统中有多个CPU核心,可以使用make -jN命令来加速编译,其中N为CPU核心数。
例如,我们可以执行以下命令:make -j4这个命令会使用4个CPU核心来编译libcurl。
编译完成后,我们可以执行make install命令来安装libcurl。
如果之前指定了安装目录,那么libcurl会被安装到指定目录下。
例如,我们可以执行以下命令:make install这个命令会将libcurl安装到/usr/local/libcurl目录下。
至此,我们已经成功地从源码编译了libcurl。
通过源码编译,我们可以自定义编译选项,以满足特定的需求。
同时,源码编译也可以帮助我们更好地理解libcurl的工作原理。
Linux下libcurl的编译和交叉编译⼀、下载curl源码⼆、创建⽬标输出⽬录 我创建了两个,⼀个放版本、⼀个放arm版本。
# mkdir build_linux build_arm三. 解压⽂件 # tar -xvf curl-7.63.0.tar.xz四. 配置并编译Linux版本: (--prefix指定编译输出安装路径 --enable-static 指定编译静态库)# ./configure --prefix=/home/gec/csdn/curl/build_linux --enable-static# make# make installARM版本:(--prefix指定编译输出安装路径 --enable-static 指定编译静态库 CC指定交叉编译⼯具链)# ./configure --host=arm-linux CC=arm-linux-gcc --prefix=/home/gec/csdn/curl/build_arm --enable-static# make# make install1.此处的 --enable-static 加上没效果,最后还是动态链接。
⾄少这个版本是这样的2.--prefix后⾯⼀定要是绝对路径,不能是相对路径五.移植到arm平台上,因为上⾯的 --enable-static 选项没起作⽤,需要将⽤到的库复制到对应路径,这⾥变态的不是从默认的/lib⽬录下读取库⽂件1.先到libcurl/bin下 readelf -d curl 查看curl的所需的库⽂件及库⽬录我这⾥显⽰库的路径是:“Library rpath: [/home/arm/share/4.开源库/curl-7.63.0/xxx/lib]”2. 在开发板上要创建同样的路径名字,并将库⽂件全部复制 mkdir /home/arm/share/4.开源库/curl-7.63.0/xxx/lib -p cp /nfs/4.开源库/curl-7.63.0/xxx/lib/ /home/arm/share/4.开源库/curl-7.63.0/xxx/lib/ 如果不做上述操作,执⾏curl命令时,不管后⾯是什么,⼀律返回:curl: (48) Error,也不提⽰是不是缺少库所造成的! 六. 复制bin下⾯的curl到开发板上,路径随意参考 不需要openssl需要openssl。
Libcurl实现断点续传⼀、LIbcurl简单介绍其实关于Liccurl的介绍最好的是看官⽅⽂档:⼏乎⼤部分的信息⾥⾯都能够查找到。
在这边简要介绍:1)跨平台特性,⼏乎所有平台都可以使⽤2)有许多其他语⾔的包装,如PHP、PYTHON等,也就是很多语⾔都可以使⽤libcurl3)Libcurl的所有接⼝被设计成线程安全(线程安全的意思是:在多线程之中可以同时调⽤⼀个API⽽不会互相影响,也就是函数可重⼊),另外要特别注意的是,任何⼀个libcurl的handle都不应该在多个线程之间共享,另外若使⽤HTTPS、FTPS需要OpenSSL或GnuTls 的⽀持。
4)⽀持IPV6,前提是在编译的时候打开相应的选项5)Libcurl性能很不错,但是若通过其他语⾔(⾮C语⾔)性能会有⼀定减弱,这和其他语⾔本⾝有关系6)Libcurl提供三种handle:easy_handle、multi_handle、share_handle easy_handle:为libcurl的最基础部分,所有的操作都是在easy_handle上进⾏的,⽐如发送、请求数据都是在其上进⾏的。
如果直接在easy_handle执⾏操作 curl_easy_perform 函数是阻塞的(即需要等到完成才返回) multi_handle:libcurl为异步操作提供的接⼝,允许调⽤⽅在⼀个线程中处理多个操作(就是easy_handle上的操作,注意是单线程下的),内部multi_handle采⽤堆栈的⽅式保存多个easy_handle,然后在⼀个线程中可以同时对多个easy_handle进⾏处理,multi_handle 的执⾏操作 curl_multi_perform 函数是⽴即返回的,不会阻塞 share_handle:有时候多个easy_handle需要分享⼀些信息,⽐如cookie,当⼀个连接获取⼀个新的cookie,就可以将这个cookie 共享到所有的连接上⼆、⼀些应⽤实例1、实现cookie共享 1)场景:客户端与服务器之间为了提⾼传输性能,建⽴了多个http连接。
libCurlopensslZlib的ARM移植libCurl/openssl/Zlib的ARM移植收藏本人使用环境Host linux(from ubuntu):jeos[just enougth OS]交叉编译器:/opt/timesys/toolchains/armv5l-linux/bin/armv5l-linux-gcc target Processor:ARM926EJ-S rev 5 (v5l)Hardware:Atmel AT91SAM9260-EK先开始libCurl 的移植过程:下载curl-7.20.0.tar.bz2解压至本目录,开始configure,由于之前一直发现配置不过,出现多次错误,这里直接给出正确的配置:cd curl-7.20.0 && ./configure--prefix=/win/530/curl/build --build=i686-linux--host=arm-linuxCC=/opt/timesys/toolchains/armv5l-linux/bin/armv5l-linux-gcc CFLAGS='-Os' --enable-debug --enable-optimize --enable-static--disable-ftp --without-zlib --disable-rtsp --disable-dict--disable-proxy --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smtp --disable-ipv6 --enable-http -enable-crypto-auth --without-gnutls --without-nss--without-ca-bundle --with-random=/dev/urandom export LDFLAGS="-static-L/opt/timesys/toolchains/armv5l-linux/lib" && configure碰到的错误:1.checking for "/dev/urandom"... configure: error: cannot check for file existence when cross compilinggoogle后发现答案:/forum/topic/137按照回答,由于是在主机上配置、编译,所以配置期间没找到适合于目标系统的随机数生成器,具体在/dev/urandom下面,但是我找了下,确实是有的:[root@openssl]# ls -al /dev/urandomcrw-rw-rw- 1 root root 1, 9 Jan 12 17:12 /dev/urandom[root@openssl]# file /dev/urandom/dev/urandom: character special引用回答的原文:#You may need to provide a parameter like'--with-random=/dev/urandom' to configure as it cannot detectthe presence of a random number generating device for a target system.2.checking for curl_socklen_t data type... unknown configure: error: cannot find data type for curl_socklen_t.在网上找了多次,没找到解决方法。
libcurl put post get 方法【实用版3篇】目录(篇1)1.介绍 libcurl 库2.libcurl 的 put、post、get 方法的定义和功能3.使用 libcurl 实现 put、post、get 方法的示例4.结论正文(篇1)一、介绍 libcurl 库libcurl 是一个用于传输数据的强大、易用、开源的 C 库。
它可以方便地处理各种网络数据传输任务,如 HTTP 请求、文件上传、FTP 文件传输等。
libcurl 支持多种协议,包括 HTTP, HTTPS, FTP, FTPS, SFTP, TFTP, LDAP, LDAPS, DICT, FILE, TELNET, RTSP, POP3, IMAP 等。
二、libcurl 的 put、post、get 方法的定义和功能1.put 方法put 方法是 HTTP 请求中的一种,用于向服务器上传文件或数据。
它将请求数据发送到服务器,然后等待服务器的响应。
2.post 方法post 方法是 HTTP 请求中的一种,用于向服务器提交数据。
它将请求数据发送到服务器,然后等待服务器的响应。
与 get 方法相比,post 方法通常用于传输较大的数据或需要保密的数据。
3.get 方法get 方法是 HTTP 请求中的一种,用于从服务器获取数据。
它向服务器发送请求,并接收服务器返回的数据作为响应。
目录(篇2)1.介绍 libcurl2.libcurl 的 put 方法3.libcurl 的 post 方法4.libcurl 的 get 方法5.结论正文(篇2)1.介绍 libcurllibcurl 是一个用于传输数据的强大且易用的库。
它可以用于多种协议,包括 HTTP, HTTPS, FTP, FTPS, SFTP, TFTP, LDAP, LDAPS, DICT, FILE, TELNET, RTSP, POP3, IMAP 等。
Linux下编译LibCURL编译环境操作系统: Red Hat Enterprise Linux Server release 5.4 64-bit编译⼯具: gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46)1. 下载libssh2库地址:将libssh2-1.4.2.tar.gz上传⾄/home⽬录下2. 编译安装libssh2库$ cd /home$ tar -zxvf libssh2-1.4.2.tar.gz$ cd libssh2-1.4.2$ ./configure --with-libssl-prefix=/usr/local/openssl$ make && make install && make clean注:如果出现:configure: error: cannot find OpenSSL or Libgcrypt 错误修改为:./configure --with-libssl-prefix=/usr/local/openssl CPPFLAGS="-I/usr/local/openssl/include" LDFLAGS="-L/usr/local/openssl/lib"3. 下载LibCURL地址:http://curl.haxx.se/download.html以curl-7.27.0.tar.gz包为例,将curl-7.27.0.tar.gz上传⾄/home⽬录下4. 解压LibCURL$ cd /home$ tar -zxvf curl-7.27.0.tar.gz$ cd curl-7.27.05. 编译并安装编译$ ./configure --with-ssl=/usr/local/openssl --with-libssh2=/usr/local --with-zlib$ make && make install清理编译时的中间⽂件$ make clean6. 使⽤在/usr/local/lib中存放的⽣成的LibCURL库libcurl.a,可以直接⽤来参与静态编译。
libcurl curlopt_writefunction 对象方法摘要:1.libcurl简介2.curlopt_writefunction的作用3.对象方法的实现4.应用场景和示例5.注意事项正文:libcurl是一个流行的C库,用于实现多种协议的HTTP请求。
它提供了丰富的选项,以满足各种网络请求的需求。
在libcurl中,curlopt_writefunction是一个重要的回调函数,用于处理HTTP响应的数据输出。
本文将详细介绍curlopt_writefunction的使用方法和应用场景。
一、libcurl简介libcurl是一个免费、开源的C库,支持多种网络协议(如HTTP, HTTPS, FTP, FTPS, SFTP, TFTP等)。
它广泛应用于各种操作系统和平台,便于开发者轻松实现网络请求。
libcurl提供了丰富的选项,允许用户自定义请求和响应的处理方式。
二、curlopt_writefunction的作用curlopt_writefunction是一个回调函数,当libcurl接收到HTTP响应数据时,会调用此函数进行处理。
该函数接收两个参数:一个是输出缓冲区,用于存储响应数据;另一个是用户数据,可以自定义。
通过设置这个选项,用户可以自定义HTTP响应数据的处理方式,例如将响应数据写入文件或输出到控制台。
三、对象方法的实现在libcurl中,可以使用以下步骤设置curlopt_writefunction:1.初始化CURL环境:使用curl_global_init()函数进行全局初始化。
2.创建CURL句柄:使用curl_easy_init()函数创建一个CURL句柄。
3.设置curlopt_writefunction:使用curl_easy_setopt()函数设置回调函数。
4.执行网络请求:使用curl_easy_perform()函数发起请求。
5.清理资源:使用curl_easy_cleanup()函数释放句柄资源。
3.1获取html网页#include<stdio.h>#include<curl/curl.h>#include<stdlib.h>int main(int argc,char*argv[]){CURL*curl;//定义CURL类型的指针CURLcode res;//定义CURLcode类型的变量,保存返回状态码if(argc!=2){printf("Usage:file<url>;\n");exit(1);}curl=curl_easy_init();//初始化一个CURL类型的指针if(curl!=NULL){//设置curl选项.其中CURLOPT_URL是让用户指定url.argv[1]中存放的命令行传进来的网址curl_easy_setopt(curl,CURLOPT_URL,argv[1]);//调用curl_easy_perform执行我们的设置.并进行相关的操作.在这里只在屏幕上显示出来.res=curl_easy_perform(curl);//清除curl操作.curl_easy_cleanup(curl);}return0;}编译gcc get_http.c-o get_http–lcurl./get_http 3.2网页下载保存实例//采用CURLOPT_WRITEFUNCTION实现网页下载保存功能#include<stdio.h>;#include<stdlib.h>;#include<unistd.h>;#include<curl/curl.h>;#include<curl/types.h>;#include<curl/easy.h>;FILE*fp;//定义FILE类型指针//这个函数是为了符合CURLOPT_WRITEFUNCTION而构造的//完成数据保存功能size_t write_data(void*ptr,size_t size,size_t nmemb,void*stream) {int written=fwrite(ptr,size,nmemb,(FILE*)fp);return written;}int main(int argc,char*argv[]){CURL*curl;curl_global_init(CURL_GLOBAL_ALL);curl=curl_easy_init();curl_easy_setopt(curl,CURLOPT_URL,argv[1]);if((fp=fopen(argv[2],"w"))==NULL){curl_easy_cleanup(curl);exit(1);}////CURLOPT_WRITEFUNCTION将后继的动作交给write_data函数处理curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_data);curl_easy_perform(curl);curl_easy_cleanup(curl);exit(0);}编译gcc save_http.c-o save_http–lcurl./save_http /tmp/baidu3.3进度条实例??显示文件下载进度//采用CURLOPT_NOPROGRESS,CURLOPT_PROGRESSFUNCTION CURLOPT_PROGRESSDATA实现文件传输进度提示功能//函数采用了gtk库,故编译时需指定gtk库//函数启动专门的线程用于显示gtk进度条bar#include<stdio.h>#include<gtk/gtk.h>#include<curl/curl.h>#include<curl/types.h>/*new for v7*/#include<curl/easy.h>/*new for v7*/GtkWidget*Bar;////这个函数是为了符合CURLOPT_WRITEFUNCTION而构造的//完成数据保存功能size_t my_write_func(void*ptr,size_t size,size_t nmemb,FILE*stream) {return fwrite(ptr,size,nmemb,stream);}//这个函数是为了符合CURLOPT_READFUNCTION而构造的//数据上传时使用size_t my_read_func(void*ptr,size_t size,size_t nmemb,FILE*stream) {return fread(ptr,size,nmemb,stream);}//这个函数是为了符合CURLOPT_PROGRESSFUNCTION而构造的//显示文件传输进度,t代表文件大小,d代表传输已经完成部分int my_progress_func(GtkWidget*bar,double t,/*dltotal*/double d,/*dlnow*/double ultotal,double ulnow){/*printf("%d/%d(%g%%)\n",d,t,d*100.0/t);*/gdk_threads_enter();gtk_progress_set_value(GTK_PROGRESS(bar),d*100.0/t);gdk_threads_leave();return0;}void*my_thread(void*ptr){CURL*curl;CURLcode res;FILE*outfile;gchar*url=ptr;curl=curl_easy_init();if(curl){outfile=fopen("test.curl","w");curl_easy_setopt(curl,CURLOPT_URL,url);curl_easy_setopt(curl,CURLOPT_WRITEDATA,outfile);curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,my_write_func);curl_easy_setopt(curl,CURLOPT_READFUNCTION,my_read_func);curl_easy_setopt(curl,CURLOPT_NOPROGRESS,0L);curl_easy_setopt(curl,CURLOPT_PROGRESSFUNCTION,my_progress_func);curl_easy_setopt(curl,CURLOPT_PROGRESSDATA,Bar);res=curl_easy_perform(curl);fclose(outfile);/*always cleanup*/curl_easy_cleanup(curl);}return NULL;}int main(int argc,char**argv){GtkWidget*Window,*Frame,*Frame2;GtkAdjustment*adj;/*Must initialize libcurl before any threads are started*/curl_global_init(CURL_GLOBAL_ALL);/*Init thread*/g_thread_init(NULL);gtk_init(&argc,&argv);Window=gtk_window_new(GTK_WINDOW_TOPLEVEL);Frame=gtk_frame_new(NULL);gtk_frame_set_shadow_type(GTK_FRAME(Frame),GTK_SHADOW_OUT); gtk_container_add(GTK_CONTAINER(Window),Frame);Frame2=gtk_frame_new(NULL);gtk_frame_set_shadow_type(GTK_FRAME(Frame2),GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(Frame),Frame2);gtk_container_set_border_width(GTK_CONTAINER(Frame2),5);adj=(GtkAdjustment*)gtk_adjustment_new(0,0,100,0,0,0);Bar=gtk_progress_bar_new_with_adjustment(adj);gtk_container_add(GTK_CONTAINER(Frame2),Bar);gtk_widget_show_all(Window);if(!g_thread_create(&my_thread,argv[1],FALSE,NULL)!=0)g_warning("can't create the thread");gdk_threads_enter();gtk_main();gdk_threads_leave();return0;}编译export PKG_CONFIG_PATH=/usr/lib/pkgconfig/gcc progress.c–o progress`pkg-config--libs–cflags gtk+-2..0`-lcurl–lgthread-2.0./progress /index.asp。
libcurl+openssl多平台编译curl-7.65.0 为例Linuxopenssl1)进⼊openssl源码根路径,如:/home/user/openssl-master,执⾏以下命令:./config; make -j82)此时会在源码根⽬录⽣成 libcrypto.a libcrypto.so libssl.a libssl.so 等相应的crypto及ssl的静态库与动态库libcurl1)进⼊libcur源码根路径,执⾏以下命令:2)依次执⾏以下命令mkdir build; cd buildmake ../ -DOPENSSL_ROOT_DIR=/home/user/openssl-master -DBUILD_SHARED_LIBS=true -DCURL_DISABLE_LDAP=true -DCURL_DISABLE_LDAPS=true -DCURL_ZLIB=falsemake -j83)此时会⽣成在 build/lib ⽬录会⽣成 libcurl.a 静态库⽂件将以下libcurl.a libssl.a libcrypto.a 或者相应.so拷贝到应⽤⼯程上链接Windowsopenssl1)进⼊openssl源码根路径,如:D:\openssl-master2)新建build.bat ⽂件,并保存以下内容:set CURPATH=%~dp0set TARGET="VC-WIN64A-masm"set VSCOMNTOOLS="C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Auxiliary\Build\vcvarsall.bat"set SHARED=call %VSCOMNTOOLS% x64mkdir buildcd buildperl ../Configure %TARGET% %SHARED% --prefix="%CURPATH%\build\prefix" --openssldir="%CURPATH%\build\install" --release perl configdata.pm --dumpnmake build_all_generatednmake PERL=no-perlnmake installcd ..脚本说明:如果编译32bit的,将TARGET修改为VC-WIN32,call %VSCOMNTOOLS% x64修改为 call %VSCOMNTOOLS% x86,如果编译debut版本,将--release修改为 --debug3)执⾏ build.bat ⽂件。
C++使用libcurl做HttpClient当使用C++做HTTP客户端时,目前通用的做法就是使用libcur l。
其官方网站的地址是/,该网站主要提供了Curl和libcurl。
Curl是命令行工具,用于完成FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及LDAP的命令的请求及接收回馈。
libcurl提供给开发者,用于使用C++跨平台的开发各种网络协议的请求及响应。
里面的文档非常齐全,不过都是英文的。
本文提供最简单的demo使用libcurl开发HttpClient。
主要包括同步的HTTP GET、HTTP POST、HTTPS GET、HTTPS POST。
下载libcurl包,如果使用Linux平台,建议下载源文件编译;如果使用Windows平台,建议下载Win32 - MSVC,下载地址是:/do wnload.html1.#ifndef __HTTP_CURL_H__2.#define __HTTP_CURL_H__3.4.#include<string>5.6.class CHttpClient7.{8.public:9.CHttpClient(void);10.~CHttpClient(void);11.12.public:13./**14.* @brief HTTP POST请求15.* @param strUrl 输入参数,请求的Url地址,如:http://16.* @param strPost 输入参数,使用如下格式para1=val 1?2=val2&…17.* @param strResponse 输出参数,返回的内容18.* @return 返回是否Post成功19.*/20.int Post(const std::string& strUrl,const std::string & strPost, std::string& strResponse);21.22./**23.* @brief HTTP GET请求24.* @param strUrl 输入参数,请求的Url地址,如:http:// 25.* @param strResponse 输出参数,返回的内容26.* @return 返回是否Post成功27.*/28.int Get(const std::string& strUrl, std::string& strR esponse);29.30./**31.* @brief HTTPS POST请求,无证书版本32.* @param strUrl 输入参数,请求的Url地址,如:https:/ /33.* @param strPost 输入参数,使用如下格式para1=val 1?2=val2&…34.* @param strResponse 输出参数,返回的内容35.* @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.36.* @return 返回是否Post成功37.*/38.int Posts(const std::string& strUrl,const std::strin g& strPost, std::string& strResponse,const char* pCaPath = N ULL);39.40./**41.* @brief HTTPS GET请求,无证书版本42.* @param strUrl 输入参数,请求的Url地址,如:https:/ /43.* @param strResponse 输出参数,返回的内容44.* @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.45.* @return 返回是否Post成功46.*/47.int Gets(const std::string& strUrl, std::string& str Response,const char* pCaPath = NULL);48.49.public:50.void SetDebug(bool bDebug);51.52.private:53.bool m_bDebug;54.};55.56.#endif57.58.[cpp] view plaincopy59.#include"httpclient.h"60.#include"curl/curl.h"61.#include<string>62.63.CHttpClient::CHttpClient(void):64.m_bDebug(false)65.{66.67.}68.69.CHttpClient::~CHttpClient(void)70.{71.72.}73.74.static int OnDebug(CURL *, curl_infotype itype,ch ar* pData,size_t size,void*)75.{76.if(itype == CURLINFO_TEXT)77.{78.//printf("[TEXT]%s\n", pData);79.}80.else if(itype == CURLINFO_HEADER_IN)81.{82.printf("[HEADER_IN]%s\n", pData);83.}84.else if(itype == CURLINFO_HEADER_OUT)85.{86.printf("[HEADER_OUT]%s\n", pData);87.}88.else if(itype == CURLINFO_DATA_IN)89.{90.printf("[DATA_IN]%s\n", pData);91.}92.else if(itype == CURLINFO_DATA_OUT)93.{94.printf("[DATA_OUT]%s\n", pData);95.}96.return0;97.}98.99.static size_t OnWriteData(void* buffer,size_t size, size_t nmemb,void* lpVoid)100.{101.std::string* str =dynamic_cast<std::string*>((std:: string*)lpVoid);102.if( NULL == str || NULL == buffer )103.{104.return-1;105.}106.107.char* pData =(char*)buffer;108.str->append(pData, size * nmemb);109.return nmemb;110.}111.112.int CHttpClient::Post(const std::string& strUrl,con st std::string& strPost, std::string& strResponse)113.{114.CURLcode res;115.CURL* curl = curl_easy_init();116.if(NULL == curl)117.{118.return CURLE_FAILED_INIT;119.}120.if(m_bDebug)121.{122.curl_easy_setopt(curl, CURLOPT_VERBOSE,1);123.curl_easy_setopt(curl,CURLOPT_DEBUGFUNCTIO N,OnDebug);124.}125.curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());126.curl_easy_setopt(curl, CURLOPT_POST,1);127.curl_easy_setopt(curl,CURLOPT_POSTFIELDS,strP ost.c_str());128.curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);129.curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);130.curl_easy_setopt(curl,CURLOPT_WRITEDATA,(voi d*)&strResponse);131.curl_easy_setopt(curl, CURLOPT_NOSIGNAL,1);132.curl_easy_setopt(curl,CURLOPT_CONNECTTIMEO UT,3);133.curl_easy_setopt(curl, CURLOPT_TIMEOUT,3);134.res = curl_easy_perform(curl);135.curl_easy_cleanup(curl);136.return res;137.}138.139.int CHttpClient::Get(const std::string& strUrl, std:: string& strResponse)140.{141.CURLcode res;142.CURL* curl = curl_easy_init();143.if(NULL == curl)144.{145.return CURLE_FAILED_INIT;146.}147.if(m_bDebug)148.{149.curl_easy_setopt(curl, CURLOPT_VERBOSE,1);150.curl_easy_setopt(curl,CURLOPT_DEBUGFUNCTIO N,OnDebug);151.}152.<pre name="code"class="cpp"> curl_easy_seto pt(curl, CURLOPT_URL, strUrl.c_str());153.curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);154.curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);155.curl_easy_setopt(curl,CURLOPT_WRITEDATA,(voi d*)&strResponse);156./**157.* 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
libcurl教程 译者注:这是一篇介绍如何使用libcurl的入门教程。文档不是逐字逐句按原文翻译,而是根据笔者对libcurl的理解,参考原文写成。文中用到的一 些例子,可能不是出自原文,而是笔者在学习过程中,写的一些示例程序(笔者使用的libcurl版本是:7.19.6)。出现在这里主要是为了更好的说明 libcurl的某些api函数的使用。许多例子都参考libcurl提供的example代码。原文example中的提供的示例程序完全使用C语言, 而这里笔者提供的例子使用C++语言。因为能力有限,对于libcurl的某些理解和使用可能有误,欢迎批评指正。
目 标 本文档介绍了在应用程序开发过程中,如何正确使用libcurl的基本方式和指导原则。文档使用C语言来调用libcurl的接口,当然也适用于其他与C 语言接近的语言。 文档主要针对使用libcurl来进行开发的人员。文档所掼的应用程序泛指你写的源代码,这些代码使用了libcurl进行数据传输。 更多关于libcurl的功能和接口信息,可以在相关的主页上查阅。 编译源码 有很多种不同的方式来编译C语言代码。这里使用UNIX平台下的编译方式。即使你使用的是其他的操作系统,你仍然可以通过阅读本文档来获取许多有用的信 息。 编译 你的编译器必须知道libcurl头文件的位置。所以在编译的时候,你要设置头文件的包含路径。可以使用curl-config工具来获取这方面的信息: $ curl-config –cflags 链接 编译完源码(这时的源代码不是指libcurl的源代码,你是你自己写的程序代码)之后,你还必须把目标文件链接成单个可执行文件。你要链接 libcurl库,以及libcurl所依赖的其他库,例如OpenSLL库。当然可能还需要一些其他的操作系统库。最后你还要设置一些编译选项,当然可 以使用curl-config工具简化操作:
$curl-config –libs 是否使用SSL 定制编译libcurl。与其他库不同的是,libcurl可以定制编译,根据实际需要是否支持某些特性,如是否支持SSL传输,像HTTPS和 FTPS。如果决定需要支持SSL,必须在编译时正确的设置。可以使用‟curl-config‟来判断libcurl库是否支持SSL:
$ curl-config –feature autoconf宏 当你编写配置脚本来检测libcurl及其相应设置时,你可以使用预定义宏。文档docs/libcurl/libcurl.m4告诉你如何使用这些宏。 跨平台的可移植的代码 libcurl的开发人员花费很大的努力,使libcurl尽可能在大多数平台上正常运行。 全局初始化 应用程序在使用libcurl之前,必须先初始化libcurl。libcurl只需初始化一次。可以使用以下语句进行初始化: curl_global_init(); curl_global_init()接收一个参数,告诉libcurl如何初始化。参数CURL_GLOBAL_ALL 会使libcurl初始化所有的子模块和一些默认的选项,通常这是一个比较好的默认参数值。还有两个可选值:
CURL_GLOBAL_WIN32 只能应用于Windows平台。它告诉libcurl初始化winsock库。如果winsock库没有正确地初始化,应用程序就不能使用socket。 在应用程序中,只要初始化一次即可。 CURL_GLOBAL_SSL 如果libcurl在编译时被设定支持SSL,那么该参数用于初始化相应的SSL库。同样,在应用程序中,只要初始化一次即可。 libcurl有默认的保护机制,如果在调用curl_easy_perform时它检测到还没有通过curl_global_init进行初始 化,libcurl会根据当前的运行时环境,自动调用全局初始化函数。但必须清楚的是,让系统自已初始化不是一个好的选择。
当应用程序不再使用libcurl的时候,应该调用curl_global_cleanup来释放相关的资源。 在程序中,应当避免多次调用curl_global_init和curl_global_cleanup。它们只能被调用一次。 libcurl提供的功能
在运行时根据libcurl支持的特性来进行开发,通常比编译时更好。可以通过调用curl_version_info函数返回的结构体来获取运行时的具 体信息,从而确定当前环境下libcurl支持的一些特性。下面是笔者在visual studio2008中调用相关函数获取libcurl版本信息的截图:
使用easy interface
首先介绍libcurl中被称为easy interface的api函数,所有这些函数都是有相同的前缀:curl_easy 。 当前版本的libcurl也提供了multi interface,关于这些接口的详细使用,在下面的章节中会有介绍。在使用multi interface之前,你首先应该理解如何使用easy interface。 要使用easy interface,首先必须创建一个easy handle,easy handle用于执行每次操作。基本上,每个线程都应该有自己的easy handle用于数据通信(如果需要的话)。千万不要在多线程之间共享同一个easy handle。下面的函数用于获取一个easy handle :
CURL *easy_handle = curl_easy_init(); 在easy handle上可以设置属性和操作(action)。easy handle就像一个逻辑连接,用于接下来要进行的数据传输。 使用curl_easy_setopt函数可以设置easy handle的属性和操作,这些属性和操作控制libcurl如何与远程主机进行数据通信。一旦在easy handle中设置了相应的属性和操作,它们将一直作用该easy handle。也就是说,重复使用easy hanle向远程主机发出请求,先前设置的属性仍然生效。 easy handle的许多属性使用字符串(以\0结尾的字节数组)来设置。通过curl_easy_setopt函数设置字符串属性时,libcurl内部会自 动拷贝这些字符串,所以在设置完相关属性之后,字符串可以直接被释放掉(如果需要的话)。
easy handle最基本、最常用的属性是URL。你应当通过CURLOPT_URL属性提供适当的URL: curl_easy_setopt(easy_handle, CURLOPT_URL, "http://blog.csdn.net/JGood "); 假设你要获取URL所表示的远程主机上的资源。你需要写一段程序用来完成数据传输,你可能希望直接保存接收到的数据而不是简单的在输出窗口中打印它们。所 以,你必须首先写一个回调函数用来保存接收到的数据。回调函数的原型如下:
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp); 可以使用下面的语句来注册回调函数,回调函数将会在接收到数据的时候被调用: curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data); 可以给回调函数提供一个自定义参数,libcurl不处理该参数,只是简单的传递: curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, &internal_struct); 如果你没有通过CURLOPT_WRITEFUNCTION属性给easy handle设置回调函数,libcurl会提供一个默认的回调函数,它只是简单的将接收到的数据打印到标准输出。你也可以通过 CURLOPT_WRITEDATA属性给默认回调函数传递一个已经打开的文件指针,用于将数据输出到文件里。
下面是一些平台相关的注意点。在一些平台上,libcurl不能直接操作由应用程序打开的文件。所以,如果使用默认的回调函数,同时通过 CURLOPT_WRITEDATA属性给easy handle传递一个文件指针,应用程序可能会执行失败。如果你希望自己的程序能跑在任何系统上,你必须避免出现这种情况。
如果以win32动态连接库的形式来使用libcurl,在设置CURLOPT_WRITEDATA属性时,你必须同时 使用CURLOPT_WRITEFUNCTION来注册回调函数。否则程序会执行失败(笔者尝试只传递一个打开的文件指针而不显式设置回调函数,程序并没 有崩溃。可能是我使用的方式不正确。)。
当然,libcurl还支持许多其他的属性,在接下来的篇幅里,你将会逐步地接触到它们。调用下面的函数,将执行真正的数据通信: success = curl_easy_perform(easy_handle); curl_easy_perfrom将连接到远程主机,执行必要的命令,并接收数据。当接收到数据时,先前设置的回调函数将被调用。libcurl可能一 次只接收到1字节的数据,也可能接收到好几K的数据,libcurl会尽可能多、及时的将数据传递给回调函数。回调函数返回接收的数据长度。如果回调函数 返回的数据长度与传递给它的长度不一致(即返回长度 != size * nmemb),libcurl将会终止操作,并返回一个错误代码。
当数据传递结束的时候,curl_easy_perform将返回一个代码表示操作成功或失败。如果需要获取更多有关通信细节的信息,你可以设置 CURLOPT_ERRORBUFFER属性,让libcurl缓存许多可读的错误信息。
easy handle在完成一次数据通信之后可以被重用。这里非常建议你重用一个已经存在的easy handle。如果在完成数据传输之后,你创建另一个easy handle来执行其他的数据通信,libcurl在内部会尝试着重用上一次创建的连接。
对于有些协议,下载文件可能包括许多复杂的子过程:日志记录、设置传输模式、选择当前文件夹,最后下载文件数据。使用libcurl,你不需要关心这一 切,你只需简单地提供一个URL,libcurl会给你做剩余所有的工作。