libcurl簡介
libcurl是一個跨平臺的網(wǎng)絡(luò)協(xié)議庫,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 協(xié)議。libcurl同樣支持HTTPS證書授權(quán),HTTP POST, HTTP PUT, FTP 上傳, HTTP基本表單上傳,代理,cookies,和用戶認證
libcurl的官網(wǎng): http://curl.haxx.se/
庫下載地址: https://github.com/curl/curl/releases/tag/curl-7_71_1
libcurl的簡單使用
初始化libcurl:
curl_global_init()
函數(shù)得到 easy interface型指針:
curl_easy_init()
設(shè)置傳輸選項:
curl_easy_setopt()
設(shè)置的傳輸選項,實現(xiàn)回調(diào)函數(shù)以完成用戶特定任務(wù):
curl_easy_setopt()
函數(shù)完成傳輸任務(wù):
curl_easy_perform()
釋放內(nèi)存:
curl_easy_cleanup()
curl_global_init
CURLcode curl_global_init(long flags);函數(shù)只能用一次。(其實在調(diào)用curl_global_cleanup 函數(shù)后仍然可再用)
如果這個函數(shù)在curl_easy_init函數(shù)調(diào)用時還沒調(diào)用,它講由libcurl庫自動調(diào)用,
所以多線程下最好主動調(diào)用該函數(shù)以防止在線程中curl_easy_init時多次調(diào)用。
注意:雖然libcurl是線程安全的,但curl_global_init是不能保證線程安全的,
所以不要在每個線程中都調(diào)用curl_global_init,應(yīng)該將該函數(shù)的調(diào)用放在主線程中。
寫入此函數(shù)避免出現(xiàn)上述風(fēng)險:
-
參數(shù):flags
CURL_GLOBAL_ALL //初始化所有的可能的調(diào)用。 CURL_GLOBAL_SSL //初始化支持 安全套接字層。 CURL_GLOBAL_WIN32 //初始化win32套接字庫。 CURL_GLOBAL_NOTHING //沒有額外的初始化。
封裝:C++使用libcurl實現(xiàn)HTTP POST和GET
在C++中使用libcurl實現(xiàn)HTTP POST和GET的源碼如下:
#include <curl/curl.h>
#include <string>
class HttpConnection {
public:
HttpConnection() {
curl_global_init(CURL_GLOBAL_ALL);
curl_ = curl_easy_init();
}
~HttpConnection() {
curl_easy_cleanup(curl_);
}
bool Post(const std::string& url, const std::string& data, std::string& response) {
if (!curl_) {
return false;
}
// set params
// set curl header
struct curl_slist* header_list = NULL;
// der_list = curl_slist_append(header_list, "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko");
header_list = curl_slist_append(header_list, "Content-Type:application/json; charset = UTF-8");
curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, header_list);
curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl_, CURLOPT_POST, 1L);
curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, data.c_str());
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, &WriteCallback);
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &response);
CURLcode res = curl_easy_perform(curl_);
return (res == CURLE_OK);
}
bool Get(const std::string& url, std::string& response) {
if (!curl_) {
return false;
}
curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl_, CURLOPT_POST, 0L);
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, &WriteCallback);
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &response);
CURLcode res = curl_easy_perform(curl_);
return (res == CURLE_OK);
}
private:
CURL* curl_ = nullptr;
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
size_t realsize = size * nmemb;
std::string* str = static_cast<std::string*>(userp);
str->append(static_cast<char*>(contents), realsize);
return realsize;
}
};
這個類中包含了兩個公共方法Post和Get,用于實現(xiàn)HTTP的POST和GET請求。
它們接受一個URL參數(shù)和可選的請求數(shù)據(jù),以及一個用于存儲響應(yīng)的字符串引用。
在使用這個類之前,需要先創(chuàng)建一個實例,并調(diào)用Post或Get方法。
如果請求成功,方法會返回true,并將服務(wù)器響應(yīng)存儲在傳遞的response字符串中。
否則,它將返回false,response將保持為空字符串。
擴展,LibCurl 實現(xiàn) Put 操作
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <check_error.h>
FILE *fp; //定義FILE類型指針
//重寫把數(shù)據(jù)讀入上傳數(shù)據(jù)流函數(shù)
size_t read_file(void* buff, size_t size, size_t nmemb, void* userp)
{
size_t sizes = fread(buff, size, nmemb, (FILE *)userp);
return sizes;
}
int main(int argc,char **argv)
{
CURLcode res; //easy_handle定義的一些錯誤碼
const char url[2096];
//初始化libcurl
if(argc!=3)
{
printf("please input url and filename");
exit(-1);
}
res = curl_global_init(CURL_GLOBAL_ALL);
if (res != CURLE_OK)
{
printf("init libcurl failed.\n" );
return -1;
}
//獲取要上傳的文件指針
FILE* r_file = fopen(argv[2], "rb");
if (0 == r_file)
{
printf( "the file %s isnot exit\n",argv[2]);
return -1;
}
CURL* easy_handle;
easy_handle = curl_easy_init();
if (0 == easy_handle)
{
printf( "get a easy_handle handle fail!");
fclose(r_file);
curl_global_cleanup();
curl_easy_cleanup(easy_handle);
return -1;
}
// 獲取文件大小
fseek(r_file, 0, 2);
int file_size = ftell(r_file);
rewind(r_file);
curl_easy_setopt(easy_handle, CURLOPT_URL, argv[1]); //獲取URL地址
curl_easy_setopt(easy_handle, CURLOPT_UPLOAD, 1); //告訴easy_handle是做上傳操作
curl_easy_setopt(easy_handle, CURLOPT_READFUNCTION, &read_file); //調(diào)用重寫的讀文件流函數(shù)
curl_easy_setopt(easy_handle, CURLOPT_READDATA, r_file); //往read_file()函數(shù)中傳入用戶自定義的數(shù)據(jù)類型
curl_easy_setopt(easy_handle, CURLOPT_INFILE, r_file); //定位作為上傳的輸入文件
curl_easy_setopt(easy_handle, CURLOPT_VERBOSE, 1); //打印出具體http協(xié)議字段
//curl_easy_setopt(easy_handle, CURLOPT_HEADER, 1);
curl_easy_setopt(easy_handle, CURLOPT_INFILESIZE, file_size); //上傳的字節(jié)數(shù)
//執(zhí)行設(shè)置好的操作
res = curl_easy_perform(easy_handle);
//獲取HTTP錯誤碼
int HTTP_flag = 0;
curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE , &HTTP_flag);
//一般清理動作
fclose(r_file);
curl_global_cleanup();
curl_easy_cleanup(easy_handle);
printf("url :%s localfile: %s\n",argv[1],argv[2]);
printf("HTTP_flag is %d\n",HTTP_flag);
// printf( "操作本地文件: file_name url:\n");
//檢測HTTP錯誤碼和執(zhí)行操作結(jié)果
if (CURLE_OK != res)
{
printf("failure\n");
return -1;
}
else
{
printf("success\n");
return 0;
}
}
在 StackOverFlow 中有一則關(guān)于 Put 操作的問題:https://stackoverflow.com/questions/7569826/send-string-in-put-request-with-libcurl
其中的回答有說:Dont use curl_easy_setopt(curl, CURLOPT_PUT, 1L);
比較好的寫法是如此:文章來源:http://www.zghlxwxcb.cn/news/detail-854644.html
curl = curl_easy_init();
if (curl) {
headers = curl_slist_append(headers, client_id_header);
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, request_url);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); /* !!! */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_struct); /* data goes here */
res = curl_easy_perform(curl);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
比較好奇 why 這樣,結(jié)果查詢 LibCurl 官方的資料說:CURLOPT_PUT 已經(jīng)被棄用了(簡單明了,所以正確的使用姿勢應(yīng)該保證是 CURLOPT_UPLOAD Option)文章來源地址http://www.zghlxwxcb.cn/news/detail-854644.html
到了這里,關(guān)于【LibCurl】C++使用libcurl實現(xiàn)HTTP POST和GET、PUT的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!