简介
https://curl.haxx.se/download.html
https://curl.haxx.se/libcurl/c/example.html
libcurl作为是一个多协议的便于客户端使用的URL传输库,基于C语言,提供C语言的API接口,支持DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet and TFTP这些协议,同时支持使用SSL证书的安全文件传输:HTTP POST, HTTP PUT, FTP 上传, 基于HTTP形式的上传、代理、Cookies、用户加密码的认证等多种应用场景。另外,libcurl是一个高移植性的库,能在绝大多数系统上运行,包括Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HPUX, IRIX, AIX, Tru64, Linux, UnixWare, HURD, Windows, Amiga, OS/2, BeOs, Mac OS X, Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS等。
下载
https://curl.haxx.se/download/curl-7.60.0.tar.gz
https://www.gitbook.com/download/pdf/book/bagder/everything-curl
编译
项目支持Visual C++ v6.0 to v15.0
项目sln文件在curl-7.60.0\projects
目录
依赖第三方库:OpenSSL, wolfSSL and SSH2
需要另外下载编译
OpenSSL
OpenSSL需要ActivePerl
build-openssl.bat支持openssl-1.0.2
build-openssl.bat vc10 x86 release
流程
主要函数
https://curl.haxx.se/libcurl/c/
curl_global_init 初始化libcrl
CURLcode curl_global_init(long flags);
flags参数取值范围
CURL_GLOBAL_ALL 初始化所有可能的调用
CURL_GLOBAL_SSL 初始化支持安全套接字层的调用
CURL_GLOBAL_WIN32 初始化WIN32套接字库
CURL_GLOBAL_NOTHING 没有额外的初始化要求
虽然libcurl
是线程安全的,但curl_global_init
是不能保证线程安全的,所以不要在每个线程中都调用curl_global_init
,应该将该函数的调用放在主线程中。
curl_easy_init() 获取CURL操作符
CURL *curl_easy_init( );
初始化一个CURL
的指针(有些像返回FILE
类型的指针一样). 相应的在调用结束时要用curl_easy_cleanup
函数清理.
curl_easy_setopt() 设置传输选项
CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
可指定libcurl
的工作方式或程序运行中改变其工作方式,实现回调函数以完成用户特定任务。
参数CURLoption
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_WRITEFUNCTION
属性给easy handle设
置回调函数,libcurl
会提供一个默认的回调函数,它只是简单的将接收到的数据打印到标准输出。你也可以通过 CURLOPT_WRITEDATA
属性给默认回调函数传递一个已经打开的文件指针,用于将数据输出到文件里。
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,指定你希望开始传递的 偏移量。
参数parameter
parameter
这个参数 既可以是个函数的指针,也可以是某个对象的指针,也可以是个long型的变量.它用什么这取决于第二个参数.
curl_easy_perform() 实现传输任务
CURLcode curl_easy_perform(CURL * easy_handle );
返回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 读本地文件错误
要获取详细的错误描述字符串,可以通过const char *curl_easy_strerror(CURLcode errornum )
这个函数取得.
https://curl.haxx.se/libcurl/c/libcurl-errors.html
curl_easy_cleanup() 释放内存
curl_easy_cleanup()
char *curl_version( )
char *curl_version( );
打印当前libcurl库的版本。
curl_slist_append与curl_slist_free_all
设置消息头
CURL *handle;
struct curl_slist *slist=NULL;
slist = curl_slist_append(slist, "pragma:");
if (slist == NULL)
return -1;
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, slist);
curl_easy_perform(handle);
curl_slist_free_all(slist); /* free the list again */
curl_easy_getinfo
获取的是应答头中特定的信息,这个函数还能获取curl的一些内部信息,如请求时间、连接时间等等。
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );
中文乱码
获取的网页内容如果是UTF_8编码,需要转换为GBK编码
std::string UTF8ToGBK(const std::string& strUTF8)
{
int len = MultiByteToWideChar(CP_UTF8, 0, strUTF8.c_str(), -1, NULL, 0);
WCHAR* wszGBK = new WCHAR[len+1];
memset(wszGBK, 0, len * 2 + 2);
MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)(LPCTSTR)strUTF8.c_str(), -1, wszGBK, len);
len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
char *szGBK = new char[len + 1];
memset(szGBK, 0, len + 1);
WideCharToMultiByte(CP_ACP,0, wszGBK, -1, szGBK, len, NULL, NULL);
std::string strTemp(szGBK);
delete[]szGBK;
delete[]wszGBK;
return strTemp;
}
std::string GBKToUTF8(const std::string& strGBK)
{
std::string strOutUTF8 = "";
WCHAR * str1;
int n = MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, NULL, 0);
str1 = new WCHAR[n];
MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, str1, n);
n = WideCharToMultiByte(CP_UTF8, 0, str1, -1, NULL, 0, NULL, NULL);
char * str2 = new char[n];
WideCharToMultiByte(CP_UTF8, 0, str1, -1, str2, n, NULL, NULL);
strOutUTF8 = str2;
delete[]str1;
str1 = NULL;
delete[]str2;
str2 = NULL;
return strOutUTF8;
}
使用LibIconv
所需文件
iconv.exe
libcharset1.dll
libiconv2.dll
libintl3.dll
命令行
curl https://www.baidu.com | iconv.exe -f utf-8 -t gbk
代码:
int covert(char *desc, char *src, char *input, size_t ilen, char *output, size_t olen)
{
char **pin = &input;
char **pout = &output;
iconv_t cd = iconv_open(desc, src);
if (cd == (iconv_t)-1)
{
return -1;
}
memset(output, 0, olen);
if (iconv(cd, (const char **)pin, &ilen, pout, &olen)) return -1;
iconv_close(cd);
return 0;
}
char *input = "中国";
size_t len = strlen(input);
char *output = (char *)malloc(OUTLEN);
covert("UTF-8", "GBK", input, len, output, OUTLEN);
printf("%s\n", output);
参考
https://blog.csdn.net/tianzhaixing2013/article/details/74726040