您的位置:首页 > 其它

libcurl使用简介

2017-03-06 11:24 232 查看
一. 是一个为网络客户端提供数据传输功能的函数库,支持HTTP,HTTPS,FTP,TELNET等协议和各种SSL安全认证。

  libcurl是开源项目,可以在其官网下载:http://curl.haxx.se/libcurl/

二. 基于libcurl的程序里主要用回调函数形式完全成任务,用户在启动传输前先设好各类参数和回调函数,当条件满足时libcurl再调用用户的回调实现特定功能。libcurl工作模式主要有两种:简单接口和多线程接口。简单接口可以实现同步、快速的文件传输;多线程接口则可生成多个连接线程以异步方式进行文件传输。

三. 使用简单接口的工作流程

调用curl_global_init()初始化libcurl

调用curl_easy_init()函数得到easyinterface型指针

调用curl_easy_setopt设置传输选项

根据curl_easy_setopt设置的传输选项,实现回调函数以完成用户特定任务

调用curl_easy_perform()函数完成传输任务

调用curl_easy_cleanup()释放内存

在整过过程中设置curl_easy_setopt()参数是最关键的,几乎所有的libcurl程序都要使用它。

四. 主要函数

CURL codecurl_global_init(longflags);

描述:

这个函数只能用一次。(其实在调用curl_global_cleanup函数后仍然可再用)

如果这个函数在curl_easy_init函数调用时还没调用,它讲由libcurl库自动完成。

参数:flags

CURL_GLOBAL_ALL //初始化所有的可能的调用。

CURL_GLOBAL_SSL //初始化支持安全套接字层。

CURL_GLOBAL_WIN32 //初始化win32套接字库。

CURL_GLOBAL_NOTHING //没有额外的初始化。

void curl_global_cleanup(void);

描述:在结束libcurl使用的时候,用来对curl_global_init做的工作清理。类似于close的函数。

char * curl_version( );

描述:打印当前libcurl库的版本。

CURL * curl_easy_init();

描述:

curl_easy_init用来初始化一个CURL的指针(有些像返回FILE类型的指针一样).相应的在调用结束时要用curl_easy_cleanup函数清理.

一般curl_easy_init意味着一个会话的开始.它的返回值一般都用在easy系列的函数中.

void curl_easy_cleanup(CURL*handle);

描述:

这个调用用来结束一个会话.与curl_easy_init配合着用.

参数:

CURL类型的指针.

CURL code curl_easy_setopt(CURL *handle, CURLoption option,parameter);

描述:

这个函数最重要了.几乎所有的curl程序都要频繁的使用它.它告诉curl库.程序将有如何的行为.比如要查看一个网页的html代码等.(这个函数有些像ioctl函数)

参数:

(1)CURL类型的指针

(2)各种CURLoption类型的选项.(都在curl.h库里有定义,man也可以查看到)

(3)parameter 这个参数既可以是个函数的指针,也可以是某个对象的指针,也可以是个long型的变量.它用什么这取决于第二个参数.

CURLoption这个参数的取值很多.具体的可以查看man手册.

CURL code curl_easy_perform(CURL *handle);

描述:

这个函数在初始化CURL类型的指针以及curl_easy_setopt完成后调用.就像字面的意思所说perform就像是个舞台.让我们设置的option运作起来.

参数:

CURL类型的指针.

五. curl_easy_setopt函数介绍

本节主要介绍curl_easy_setopt中跟http相关的参数。注意本节的阐述都是以libcurl作为主体,其它为客体来阐述的。


CURLOPT_URL

设置访问URL

CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA

回调函数原型为:size_t function( void *ptr, size_t size, size_t nmemb, void *stream);

函数将在libcurl接收到数据后被调用,因此函数多做数据保存的功能,如处理下载文件。CURLOPT_WRITEDATA用于表明CURLOPT_WRITEFUNCTION函数中的stream指针的来源。

CURLOPT_HEADERFUNCTION,CURLOPT_HEADERDATA

回调函数原型为size_t function( void *ptr, size_t size,size_t nmemb, void *stream);

libcurl一旦接收到http头部数据后将调用该函数。CURLOPT_WRITEDATA传递指针给libcurl,该指针表明CURLOPT_HEADERFUNCTION函数的stream指针的来源。

CURLOPT_READFUNCTION,CURLOPT_READDATA

libCurl需要读取数据传递给远程主机时将调用CURLOPT_READFUNCTION指定的函数.

函数原型是:size_t function(void *ptr, size_t size, size_t nmemb,void *stream);

CURLOPT_READDATA 表明CURLOPT_READFUNCTION函数原型中的stream指针来源。

CURLOPT_NOPROGRESS,CURLOPT_PROGRESSFUNCTION,CURLOPT_PROGRESSDATA

跟数据传输进度相关的参数。CURLOPT_PROGRESSFUNCTION指定的函数正常情况下每秒被libcurl调用一次,为了使CURLOPT_PROGRESSFUNCTION被调用,CURLOPT_NOPROGRESS必须被设置为false,CURLOPT_PROGRESSDATA指定的参数将作为CURLOPT_PROGRESSFUNCTION指定函数的第一个参数

CURLOPT_TIMEOUT,CURLOPT_CONNECTIONTIMEOUT:

CURLOPT_TIMEOUT由于设置传输时间,CURLOPT_CONNECTIONTIMEOUT设置连接等待时间

CURLOPT_FOLLOWLOCATION

设置重定位URL

CURLOPT_RANGE,CURLOPT_RESUME_FROM:

断点续传相关设置。CURLOPT_RANGE指定char*参数传递给libcurl,用于指明http域的RANGE头域,例如:

表示头500个字节:bytes=0-499

表示第二个500字节:bytes=500-999

表示最后500个字节:bytes=-500

表示500字节以后的范围:bytes=500-

第一个和最后一个字节:bytes=0-0,-1

同时指定几个范围:bytes=500-600,601-999

CURLOPT_RESUME_FROM传递一个long参数给libcurl,指定你希望开始传递的偏移量。

附:

CURLOPT_HEADER:设为1,则在返回的内容里包含http header;

CURLOPT_FOLLOWLOCATION:设为0,则不会自动301,302跳转;

*CURLOPT_INFILESIZE: 当你上传一个文件到远程站点,这个选项告诉PHP你上传文件的大小。

*CURLOPT_VERBOSE: 如果你想CURL报告每一件意外的事情,设置这个选项为一个非零值。

*CURLOPT_HEADER: 如果你想把一个头包含在输出中,设置这个选项为一个非零值。

*CURLOPT_NOPROGRESS: 如果你不会PHP为CURL传输显示一个进程条,设置这个选项为一个非零值。

注意:PHP自动设置这个选项为非零值,你应该仅仅为了调试的目的来改变这个选项。

*CURLOPT_NOBODY: 如果你不想在输出中包含body部分,设置这个选项为一个非零值。

*CURLOPT_FAILONERROR: 如果你想让PHP在发生错误(HTTP代码返回大于等于300)时,不显示,设置这个选项为一人非零值。默认行为是返回一个正常页,忽略代码。

*CURLOPT_UPLOAD: 如果你想让PHP为上传做准备,设置这个选项为一个非零值。

*CURLOPT_POST: 如果你想PHP去做一个正规的HTTP POST,设置这个选项为一个非零值。这个POST是普通的 application/x-www-from-urlencoded 类型,多数被HTML表单使用。

*CURLOPT_FTPLISTONLY: 设置这个选项为非零值,PHP将列出FTP的目录名列表。

*CURLOPT_FTPAPPEND: 设置这个选项为一个非零值,PHP将应用远程文件代替覆盖它。

*CURLOPT_NETRC: 设置这个选项为一个非零值,PHP将在你的 ~./netrc 文件中查找你要建立连接的远程站点的用户名及密码。

*CURLOPT_FOLLOWLOCATION: 设置这个选项为一个非零值(象 “Location: “)的头,服务器会把它当做HTTP头的一部分发送(注意这是递归的,PHP将发送形如 “Location: “的头)。

*CURLOPT_PUT: 设置这个选项为一个非零值去用HTTP上传一个文件。要上传这个文件必须设置CURLOPT_INFILE和CURLOPT_INFILESIZE选项.

*CURLOPT_MUTE: 设置这个选项为一个非零值,PHP对于CURL函数将完全沉默。

*CURLOPT_TIMEOUT: 设置一个长整形数,作为最大延续多少秒。

*CURLOPT_LOW_SPEED_LIMIT: 设置一个长整形数,控制传送多少字节。

*CURLOPT_LOW_SPEED_TIME: 设置一个长整形数,控制多少秒传送CURLOPT_LOW_SPEED_LIMIT规定的字节数。

*CURLOPT_RESUME_FROM: 传递一个包含字节偏移地址的长整形参数,(你想转移到的开始表单)。

*CURLOPT_SSLVERSION: 传递一个包含SSL版本的长参数。默认PHP将被它自己努力的确定,在更多的安全中你必须手工设置。

*CURLOPT_TIMECONDITION: 传递一个长参数,指定怎么处理CURLOPT_TIMEVALUE参数。你可以设置这个参数为TIMECOND_IFMODSINCE 或 TIMECOND_ISUNMODSINCE。这仅用于HTTP。

*CURLOPT_TIMEVALUE: 传递一个从1970-1-1开始到现在的秒数。这个时间将被CURLOPT_TIMEVALUE选项作为指定值使用,或被默认TIMECOND_IFMODSINCE使用。

下列选项的值将被作为字符串:

*CURLOPT_URL: 这是你想用PHP取回的URL地址。你也可以在用curl_init()函数初始化时设置这个选项。

*CURLOPT_USERPWD: 传递一个形如[username]:[password]风格的字符串,作用PHP去连接。

*CURLOPT_PROXYUSERPWD: 传递一个形如[username]:[password] 格式的字符串去连接HTTP代理。

*CURLOPT_RANGE: 传递一个你想指定的范围。它应该是”X-Y”格式,X或Y是被除外的。HTTP传送同样支持几个间隔,用逗句来分隔(X-Y,N-M)。

*CURLOPT_POSTFIELDS: 传递一个作为HTTP “POST”操作的所有数据的字符串。

*CURLOPT_REFERER: 在HTTP请求中包含一个”referer”头的字符串。

*CURLOPT_USERAGENT: 在HTTP请求中包含一个”user-agent”头的字符串。

*CURLOPT_FTPPORT: 传递一个包含被ftp “POST”指令使用的IP地址。这个POST指令告诉远程服务器去连接我们指定的IP地址。这个字符串可以是一个IP地址,一个主机名,一个网络界面名(在UNIX下),或是‘-’(使用系统默认IP地址)。

*CURLOPT_COOKIE: 传递一个包含HTTP cookie的头连接。

*CURLOPT_SSLCERT: 传递一个包含PEM格式证书的字符串。

*CURLOPT_SSLCERTPASSWD: 传递一个包含使用CURLOPT_SSLCERT证书必需的密码。

*CURLOPT_COOKIEFILE: 传递一个包含cookie数据的文件的名字的字符串。这个cookie文件可以是Netscape格式,或是堆存在文件中的HTTP风格的头。

*CURLOPT_CUSTOMREQUEST: 当进行HTTP请求时,传递一个字符被GET或HEAD使用。为进行DELETE或其它操作是有益的,更Pass a string to be used instead of GET or HEAD when doing an HTTP request. This is useful for doing or another, more obscure, HTTP request.

注意: 在确认你的服务器支持命令先不要去这样做。

下列的选项要求一个文件描述(通过使用fopen()函数获得):

*CURLOPT_FILE: 这个文件将是你放置传送的输出文件,默认是STDOUT.

*CURLOPT_INFILE: 这个文件是你传送过来的输入文件。

*CURLOPT_WRITEHEADER: 这个文件写有你输出的头部分。

*CURLOPT_STDERR: 这个文件写有错误而不是stderr。

六. curl_easy_perform函数说明(error状态码)

该函数完成curl_easy_setopt指定的所有选项,本节重点介绍curl_easy_perform的返回值。返回0意味一切ok,非0代表错误发生。主要错误码说明:


CURLE_OK

任务完成一切都好

CURLE_UNSUPPORTED_PROTOCOL

不支持的协议,由URL的头部指定

CURLE_COULDNT_CONNECT

不能连接到remote主机或者代理

CURLE_REMOTE_ACCESS_DENIED

访问被拒绝

CURLE_HTTP_RETURNED_ERROR

Http返回错误

CURLE_READ_ERROR

读本地文件错误

七. 获取html网页

#include<stdio.h>
#include<curl/curl.h>
#include<stdlib.h>

intmain(int argc, char *argv[])
{
CURL*curl;             //定义CURL类型的指针
CURLcoderes;           //定义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 www.baidu.com

八. 网页下载保存实例

//采用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_twrite_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
intwritten = fwrite(ptr, size, nmemb, (FILE *)fp);
returnwritten;
}

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 www.baidu.com /tmp/baidu

九. 进度条实例显示文件下载进度

//采用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)
{
returnfwrite(ptr, size, nmemb, stream);
}

//这个函数是为了符合CURLOPT_READFUNCTION而构造的
//数据上传时使用
size_t my_read_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
returnfread(ptr, size, nmemb, stream);
}

//这个函数是为了符合CURLOPT_PROGRESSFUNCTION而构造的
//显示文件传输进度,t代表文件大小,d代表传输已经完成部分
int my_progress_func(GtkWidget *bar,
doublet, /* dltotal */
doubled, /* dlnow */
doubleultotal,
doubleulnow)
{
/* 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();

return 0;
}

void* my_thread(void *ptr)
{
CURL*curl;
CURLcoderes;
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);
}

returnNULL;
}

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'tcreate the thread");

gdk_threads_enter();

gtk_main();

gdk_threads_leave();

return 0;
}


编译exportPKG_CONFIG_PATH=/usr/lib/pkgconfig/

gcc progress.c –o progress
pkg-config --libs –cflags gtk+-2..0
-lcurl –lgthread-2.0

./progress http://software.sky-union.cn/index.asp

十. 断点续传实例

//采用CURLOPT_RESUME_FROM_LARGE实现文件断点续传功能
#include<stdlib.h>
#include<stdio.h>
#include<sys/stat.h>
#include<curl/curl.h>

//这个函数为CURLOPT_HEADERFUNCTION参数构造
/*从http头部获取文件size*/
size_tgetcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void*stream)
{
int r;
longlen = 0;

/*_snscanf() is Win32 specific */
//r = _snscanf(ptr, size * nmemb, "Content-Length: %ld\n",&len);
r= sscanf(ptr, "Content-Length: %ld\n", &len);
if(r) /* Microsoft: we don't read the specs */
*((long*) stream) = len;

returnsize * nmemb;
}

/*保存下载文件*/
size_t wirtefunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
returnfwrite(ptr, size, nmemb, stream);
}

/*读取上传文件*/
size_treadfunc(void *ptr, size_t size, size_t nmemb, void *stream)
{
FILE*f = stream;
size_tn;

if(ferror(f))
returnCURL_READFUNC_ABORT;

n= fread(ptr, size, nmemb, f) * size;

return n;
}

//下载或者上传文件函数
int download(CURL *curlhandle, const char * remotepath, const char *localpath,
longtimeout, long tries)
{
FILE* f;
curl_off_t local_file_len = -1 ;
long filesize =0 ;
CURLcoder = CURLE_GOT_NOTHING;
int c;

structstat file_info;
intuse_resume = 0;

/*得到本地文件大小*/
//if(access(localpath,F_OK)==0)
if(stat(localpath,&file_info) == 0)
{
local_file_len = file_info.st_size;
use_resume = 1;
}

//采用追加方式打开文件,便于实现文件断点续传工作
f= fopen(localpath, "ab+");
if(f == NULL)
{
perror(NULL);
return 0;
}

//curl_easy_setopt(curlhandle,CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curlhandle,CURLOPT_URL, remotepath);
curl_easy_setopt(curlhandle,CURLOPT_CONNECTTIMEOUT, timeout);  // 设置连接超时,单位秒

//设置http头部处理函数
curl_easy_setopt(curlhandle,CURLOPT_HEADERFUNCTION, getcontentlengthfunc);
curl_easy_setopt(curlhandle,CURLOPT_HEADERDATA, &filesize);

//设置文件续传的位置给libcurl
curl_easy_setopt(curlhandle,CURLOPT_RESUME_FROM_LARGE, use_resume?local_file_len:0);
curl_easy_setopt(curlhandle,CURLOPT_WRITEDATA, f);
curl_easy_setopt(curlhandle,CURLOPT_WRITEFUNCTION, wirtefunc);
//curl_easy_setopt(curlhandle,CURLOPT_READFUNCTION, readfunc);
//curl_easy_setopt(curlhandle,CURLOPT_READDATA, f);
curl_easy_setopt(curlhandle,CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(curlhandle,CURLOPT_VERBOSE, 1L);
r= curl_easy_perform(curlhandle);
fclose(f);

if(r == CURLE_OK)
return 1;
else
{
fprintf(stderr,"%s\n", curl_easy_strerror(r));
return 0;
}
}

int main(int c, char **argv)
{
CURL*curlhandle = NULL;
curl_global_init(CURL_GLOBAL_ALL);
curlhandle= curl_easy_init();

//download(curlhandle,"ftp://user:pass@host/path/file", "C:\\file",0, 3);
download(curlhandle, "http://software.sky-union.cn/index.asp","/work/index.asp",1,3);

curl_easy_cleanup(curlhandle);

curl_global_cleanup();

return 0;
}


编译gcc resume.c -o resume –lcurl

./resume

十一. LibCurl调试实例

//采用CURLOPT_DEBUGFUNCTION参数实现libcurl调试功能
#include<stdio.h>
#include<curl/curl.h>

struct data
{
chartrace_ascii; /* 1 or 0 */
};

static void dump(const char *text,
FILE*stream, unsigned char *ptr, size_t size,
charnohex)
{
size_t i;
size_t c;
unsigned int width = 0x10;

if(nohex)
{
/*without the hex output, we can fit more on screen */
width = 0x40;

fprintf(stream,"%s, %zd bytes (0x%zx)\n", text, size, size);

for(i=0;i<size; i+= width)
{
fprintf(stream,"%04zx: ", i);
if(!nohex)
{
/*hex not disabled, show it */
for(c= 0; c < width; c++)
if(i+c< size)
fprintf(stream,"%02x ", ptr[i+c]);
else
fputs("  ", stream);
}

for(c= 0; (c < width) && (i+c < size); c++)
{
/*check for 0D0A; if found, skip past and start a new line of output*/
if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D &&ptr[i+c+1]==0x0A)
i+=(c+2-width);
break;
}

fprintf(stream,"%c",
(ptr[i+c]>=0x20)&& (ptr[i+c]<0x80)?ptr[i+c]:'.');
/*check again for 0D0A, to avoid an extra \n if it's at width */
if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D &&ptr[i+c+2]==0x0A)
{
i+=(c+3-width);
break;
}
}
fputc('\n',stream); /* newline */
}
fflush(stream);
}

static int my_trace(CURL *handle, curl_infotype type,
char*data, size_t size,
void*userp)
{
structdata *config = (struct data *)userp;
constchar *text;
(void)handle;/* prevent compiler warning */

switch(type)
{
caseCURLINFO_TEXT:
fprintf(stderr,"== Info: %s", data);

default:/* in case a new one is introduced to shock us */
return 0;

caseCURLINFO_HEADER_OUT:
text= "=> Send header";
break;

caseCURLINFO_DATA_OUT:
text= "=> Send data";
break;

caseCURLINFO_SSL_DATA_OUT:
text= "=> Send SSL data";
break;

caseCURLINFO_HEADER_IN:
text= "<= Recv header";
break;

caseCURLINFO_DATA_IN:
text= "<= Recv data";
break;

caseCURLINFO_SSL_DATA_IN:
text= "<= Recv SSL data";
break;
}

dump(text,stderr, (unsigned char *)data, size, config->trace_ascii);
return 0;
}

int main(void)
{
CURL* curl;
CURLcode res;
struct data config;

config.trace_ascii= 1; /* enable ascii tracing */
...
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: