libcurl在VC下编译主要有以下几步
1. 下载msvc平台的libcurl,压缩包中有一些头文件,dll文件,lib文件
2.
3.
4.
5.
6. 此后要发布自己编译的程序,一定要记住把libcurl.dll和zlib1.dll这两个文件一起拷贝到程序目录下
全局初始化
curl_global_init();
CURL_GLOBAL_WIN32
CURL_GLOBAL_SSL
使用easy interface
要使用easy interface,首先必须创建一个easy handle,easy handle用于执行每次操作。基本上,每个线程都应该有自己的easy handle用于数据通信(如果需要的话)。千万不要在多线程之间共享同一个easy handle。下面的函数用于获取一个easy handle :
CURL *easy_handle = curl_easy_init();
curl_easy_setopt(easy_handle, CURLOPT_URL, "http://blog.youkuaiyun.com/JGood
size_t write_data(void
curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, &internal_struct);
success = curl_easy_perform(easy_handle);
size_t process_data(void *buffer, size_t size, size_t nmemb, void *user_p) { FILE *fp = (FILE *)user_p; size_t return_size = fwrite(buffer, size, nmemb, fp); cout << (char *)buffer << endl;
return return_size; }
int main(int argc, char **argv) { // 初始化libcurl CURLcode return_code; return_code = curl_global_init(CURL_GLOBAL_WIN32); if (CURLE_OK != return_code) { cerr << "init libcurl failed." << endl; return -1; }
// 获取easy handle CURL *easy_handle = curl_easy_init();
if (NULL == easy_handle)
{
cerr << "get a easy handle failed." << endl;
curl_global_cleanup();
return -1;
}
FILE *fp = fopen("data.html", "ab+"); // // 设置easy handle属性 curl_easy_setopt(easy_handle, CURLOPT_URL, http://blog.youkuaiyun.com/JGood);
curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, &process_data);
curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, fp);
// 执行数据请求 curl_easy_perform(easy_handle);
// 释放资源
fclose(fp);
curl_easy_cleanup(easy_handle);
curl_global_cleanup();
return 0;
}
1. 创建easy handle或者重用先前创建的easy handle。
2. 设置CURLOPT_URL属性。
3. 编写回调函数。在执行上传的时候,libcurl通过回调函数读取要上传的数据。(如果要从远程服务器下载数据,可以通过回调来保存接收到的数据。)回调函数的原型如下:
size_t function(char *bufptr, size_t size, size_t nitems, void *userp);
4. 注册回调函数,设置自定义指针。语法如下:
// 注册回调函数 curl_easy_setopt(easy_handle, CURLOPT_READFUNCTION, read_function); // 设置自定义指针 curl_easy_setopt(easy_handle, CURLOPT_READDATA, &filedata);
5. 告诉libcurl,执行的是上传操作。
curl_easy_setopt(easy_handle, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(easy_handle, CURLOPT_INFILESIZE_LARGE, file_size);
6. 调用curl_easy_perform。
size_t read_data(void *buffer, size_t size, size_t nmemb, void *user_p) { return fread(buffer, size, nmemb, (FILE *)user_p); }
int main(int argc, char **argv) { // 初始化libcurl CURLcode code;
code = curl_global_init(CURL_GLOBAL_WIN32); if (code != CURLE_OK) { cerr << "init libcurl failed." << endl; return -1; }
FILE *fp = fopen("a.html", "rb"); if (NULL == fp) {
cout << "can't open file." << endl; curl_global_cleanup(); return -1; }
// 获取文件大小 fseek(fp, 0, 2);
int file_size = ftell(fp); rewind(fp);
// 获取easy handle
CURL *easy_handle = NULL; easy_handle = curl_easy_init(); if (NULL == easy_handle) { cerr << "get a easy handle failed." << endl; fclose(fp); curl_global_cleanup(); return -1;
}
// 设置eash handle属性 curl_easy_setopt(easy_handle, CURLOPT_URL, ftp://127.0.0.1/upload.html); curl_easy_setopt(easy_handle, CURLOPT_UPLOAD, 1L); curl_easy_setopt(easy_handle, CURLOPT_READFUNCTION, &read_data); curl_easy_setopt(easy_handle, CURLOPT_READDATA, fp); curl_easy_setopt(easy_handle, CURLOPT_INFILESIZE_LARGE, file_size);
// 执行上传操作 code = curl_easy_perform(easy_handle); if (code == CURLE_OK) { cout << "upload successfully." << endl; }
// 释放资源 fclose(fp);
curl_easy_cleanup(easy_handle);
curl_global_cleanup();
return 0; }
关于密码
curl_easy_setopt(easy_handle, CURLOPT_USERPWD, "user_name:password");
curl_easy_setopt(easy_handle, CURLOPT_PROXYUSERPWD, "user_name:password");
curl_easy_setopt(easy_handle, CURLOPT_NETRC, 1L);
curl_easy_setopt(easy_handle, CURLOPT_KEYPASSWD, "keypassword");
HTTP验证
curl_easy_setopt(easy_handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_easy_setopt(easy_handle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
curl_easy_setopt(easy_handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
// curl_easy_setopt(easy_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
HTTP Post
int main(int argc, char **argv) { code = curl_global_init(CURL_GLOBAL_WIN32); CURL *easy_handle = curl_easy_init();
curl_easy_setopt(easy_handle, CURLOPT_URL, http://localhost:2210/Default.aspx); // 单个域post curl_easy_setopt(easy_handle, CURLOPT_POSTFIELDS, "name=jgood&address=hangzhou");
code = curl_easy_perform(easy_handle);
curl_easy_cleanup(easy_handle);
curl_global_cleanup();
return 0; }
上面的代码够简单吧~_~ 有时候,我们需要提交一些二进制数据到HTTP服务器,使用方法一就不行了,因为方法一中实际提交的是一个字符串,字符串遇到\0就表示结束了。所以在上传二进制数据的时候,必须明确的告诉libcurl要提交的数据的长度。在上传二进制数据的时候,还应该设置提交的Content-Type头信息。下面的示例代码:
int main(int argc, char **argv) { curl_global_init(CURL_GLOBAL_WIN32);
CURL *easy_handle = curl_easy_init();
// 上传二进制数据 char data[] = { 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0 }; curl_slist *http_headers = NULL; http_headers = curl_slist_append(http_headers, "Content-Type: text/xml");
curl_easy_setopt(easy_handle, CURLOPT_HTTPHEADER, http_headers);
curl_easy_setopt(easy_handle, CURLOPT_URL, http://localhost:2210/Default.aspx); curl_easy_setopt(easy_handle, CURLOPT_POSTFIELDS, data); curl_easy_setopt(easy_handle, CURLOPT_POSTFIELDSIZE, sizeof(data));
curl_easy_perform(easy_handle);
curl_slist_free_all(http_headers); curl_easy_cleanup(easy_handle); curl_global_cleanup();
return 0; }
上面介绍的两种方式,可以完成大部分的HTTP POST操作。但上面的两种方式都不支持multi-part formposts。Multi-part formposts被认为是提交二进制数据(或大量数据)的更好方法,可以在RFC1867, RFC2388中找到他们的定义。何为Multi-part?其实,就我理解,就是在Post提交的时候,有不同的数据单元,每个单元有自己的名称与内容,内容可以是文本的,也可以是二进制的。同时,每个数据单元都可以有自己的消息头,MIME类型,这些数据单元组成一个链表,提交到HTTP服务器。libcurl提供了方便的api用于支持multi-part formposts。使用curl_formadd函数,可以添加不同的数据数据单元,然后提交到服务器。下面是一个multi-part formposts的例子(更详细的使用,请参考:http://curl.haxx.se/libcurl/c/curl_formadd.html
int main()
{
// 使用multi-parts form post curl_easy_setopt(easy_handle, CURLOPT_URL, http://localhost:2210/Default.aspx);
curl_httppost *post = NULL;
curl_httppost *last = NULL;
// 文本数据 curl_formadd(&post, &last, CURLFORM_COPYNAME, "name", CURLFORM_COPYCONTENTS, "JGood", CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "address", CURLFORM_COPYCONTENTS, "HangZhou", CURLFORM_END);
// 文本文件中的数据 curl_formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_FILECONTENT, "ReadMe.txt", CURLFORM_END); curl_easy_setopt(easy_handle, CURLOPT_HTTPPOST, post); curl_easy_perform(easy_handle);
curl_formfree(post); curl_easy_cleanup(easy_handle); curl_global_cleanup();
return 0; }
curl_easy_setopt(easy_handle, CURLOPT_HTTPGET, 1L);
显示进度
int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
在C++中使用libcurl
class AClass { static size_t write_data(void *ptr, size_t size, size_t nmemb, void *ourpointer) { } }
代理
代理选项
curl_easy_setopt(easy_handle, CURLOPT_PROXY, "proxy-host.com:8080");
curl_easy_setopt(easy_handle, CURLOPT_PROXY, "proxy-host.com"); curl_easy_setopt(easy_handle, CURLOPT_PROXYPORT, "8080"); // 端口号是用字符串还是整数??
curl_easy_setopt(easy_handle, CURLOPT_PROXYUSERPWD, "user:password");
curl_easy_setopt(easy_handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
环境变量
SSL和代理
代理通道(Tunneling Through Proxy)
curl_easy_setopt(easy_handle, CURLOPT_HTTPPROXYTUNNEL, 1L);
自动配置代理
持久化的好处(Persistence Is The Way to Happiness)
libcurl使用的HTTP消息头
Host
Pragma
Accept
headers = curl_slist_append(headers, "Accept: Agent-007"); headers = curl_slist_append(headers, "Host: munged.host.line");
删除消息头
headers = curl_slist_append(headers, "Accept:");
强制分块传输(Enforcing chunked transfer-encoding)
HTTP版本
curl_easy_setopt(easy_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
FTP自定义命令
headers = curl_slist_append(headers, "DELE file-to-remove");
curl_easy_setopt(easyhandle, CURLOPT_QUOTE, headers);
// curl_easy_setopt(easyhandle, CURLOPT_POSTQUOTE, headers); // 在数据传输之后操行删除操作
curl_easy_perform(easyhandle); curl_slist_free_all(headers);
FTP自定义CUSTOMREQUEST
int main(int argc, char **argv) { curl_global_init(CURL_GLOBAL_WIN32);
CURL *easy_handle = curl_easy_init(); curl_easy_setopt(easy_handle, CURLOPT_URL, "ftp://127.0.0.1/"); curl_easy_setopt(easy_handle, CURLOPT_CUSTOMREQUEST, "NLST");
curl_easy_perform(easy_handle);
curl_easy_cleanup(easy_handle); curl_global_cleanup();
return 0;
}