libcurl介绍
libcurl是一个跨平台的网络协议库,支持http, https,ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权,HTTP POST,HTTP PUT, FTP 上传, HTTP基本表单上传,代理,cookies和用户认证。
基本编程框架
- 调用curl_global_init()初始化libcurl
- 调用curl_easy_init()函数获得curl的指针
- 调用curl_easy_setopt()设置传输选项
- 调用curl_easy_perform()函数完成传输任务
- 调用curl_easy_cleanup()释放内存
编程注意事项
- curl_global_init():这个函数只能用一次。(其实在调用curl_global_cleanup函数后仍然可再用)。如果这个函数在curl_easy_init函数调用时还没调用,它讲由libcurl库自动调用,所以多线程下最好主动调用该函数以防止在线程中curl_easy_init时多次调用。虽然libcurl是线程安全的,但curl_global_init是不能保证线程安全的,所以不要在每个线程中都调用curl_global_init,应该将该函数的调用放在主线程中。
- curl_global_cleanup():在结束libcurl使用的时候,用来对curl_global_init做的工作清理。类似于close的函数。虽然libcurl是线程安全的,但curl_global_cleanup是不能保证线程安全的,所以不要在每个线程中都调用curl_global_init,应该将该函数的调用放在主线程中。
- curl_easy_init( )与curl_easy_cleanup():成对使用,用来初始化一个CURL的指针与释放CURL的指针。
常用的网站
该网站有libcurl的API的详细介绍,还有一些例子
The libcurl API
使用Postman生成代码
由于libcurl库的参数设置十分多,我们可以使Postman来生成代码。
- 配置请求的参数,点击code
- 左边选择语言,右边就能生成对应语言的代码。
例子
simple HTTP POST using the easy interface
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if(curl) {
/* First set the URL that is about to receive our POST. This URL can
just as well be an https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi");
/* Now specify the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl");
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
HTTP PUT using CURLOPT_POSTFIELDS
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <curl/curl.h>
static const char olivertwist[]=
"Among other public buildings in a certain town, which for many reasons "
"it will be prudent to refrain from mentioning, and to which I will assign "
"no fictitious name, there is one anciently common to most towns, great or "
"small: to wit, a workhouse; and in this workhouse was born; on a day and "
"date which I need not trouble myself to repeat, inasmuch as it can be of "
"no possible consequence to the reader, in this stage of the business at "
"all events; the item of mortality whose name is prefixed";
/* ... to the head of this chapter. String cut off to stick within the C90
509 byte limit. */
/*
* This example shows an HTTP PUT operation that sends a fixed buffer with
* CURLOPT_POSTFIELDS to the URL given as an argument.
*/
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
char *url;
if(argc < 2)
return 1;
url = argv[1];
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
curl = curl_easy_init();
if(curl) {
struct curl_slist *headers = NULL;
/* default type with postfields is application/x-www-form-urlencoded,
change it if you want */
headers = curl_slist_append(headers, "Content-Type: literature/classic");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
/* pass on content in request body. When CURLOPT_POSTFIELDSIZE is not used,
curl does strlen to get the size. */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, olivertwist);
/* override the POST implied by CURLOPT_POSTFIELDS
*
* Warning: CURLOPT_CUSTOMREQUEST is problematic, especially if you want
* to follow redirects. Be aware.
*/
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
/* specify target URL, and note that this URL should include a file
name, not only a directory */
curl_easy_setopt(curl, CURLOPT_URL, url);
/* Now run off and do what you have been told! */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
/* free headers */
curl_slist_free_all(headers);
}
curl_global_cleanup();
return 0;
}
文件上传
#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
static size_t write_data(char *p, size_t size, size_t nmemb, void *userdata)
{
char *buf = malloc(size * nmemb + 1);
memcpy(buf, p, size * nmemb);
buf[size * nmemb] = 0x00;
log_debug(">> %s", buf);
free(buf);
return size * nmemb;
}
/**
* @brief 文件上传
* @param path 文件路径
* @param url url地址
* @return
*/
int http_file_upload(char *path, char *url)
{
CURL *curl;
CURLcode res;
/* get a curl handle */
curl = curl_easy_init();
if (!curl) {
return -1;
}
mgLog_debug("url: %s", url);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Content-Type: multipart/form-data");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
struct curl_httppost *post = NULL;
struct curl_httppost *last = NULL;
curl_formadd(&post, &last, CURLFORM_COPYNAME, "key", CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_FILE, path, CURLFORM_END);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
/*执行数据请求*/
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
log_debug("curl_easy_perform() failed: %s", curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
curl_formfree(post);
return 0;
}
void test(void)
{
curl_global_init(CURL_GLOBAL_ALL);
http_file_upload("/tmp/test.txt","http://test.com/upload");
curl_global_cleanup();
}