1、簡介
https://github.com/curl/curl
https://curl.se/libcurl/
https://curl.se/download.html
libcurl 是一個免費且易于使用的客戶端 URL 傳輸 庫,支持DICT,F(xiàn)ILE,F(xiàn)TP,F(xiàn)TPS,GOPHER,GOPHERS,HTTP,HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POPP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP, SMB、SMBS、SMTP、SMTPS、TELNET 和 TFTP。libcurl 支持 SSL 證書,HTTP POST,HTTP PUT,F(xiàn)TP 上傳,基于 HTTP 表單的上傳, 代理、HTTP/2、HTTP/3、cookie、用戶+密碼身份驗證(基本、 摘要,NTLM,協(xié)商,Kerberos),文件傳輸恢復,http代理 隧道等等!
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等等…
2、下載和編譯
2.1 下載
官網(wǎng)下載地址:
https://curl.se/download.html
- curl executable
您將從此鏈接獲得預構建的“curl”二進制文件(或者在某些情況下,使用此鏈接帶您訪問的頁面上提供的信息)。您可能會也可能不會將“l(fā)ibcurl”安裝為共享庫/ DLL。 - libcurl development
這是用于 libcurl 開發(fā)的 - 但并不總是包含 libcurl 本身。很可能是頭文件和文檔。如果你打算編譯或構建使用 libcurl 的東西,這很可能是你想要的包。 - libcurl
這是一個純二進制 libcurl 包,可能包括頭文件和文檔,但沒有命令行工具和其他問題。如果你想讓一個使用 libcurl 的程序使用 libcurl,這很可能是你想要的包。 - source code
-您不會從此鏈接下載預構建的二進制文件。相反,您將獲得一個指向帶有 curl 源的網(wǎng)站的鏈接,該鏈接已針對您的平臺進行了調(diào)整。您需要設置編譯器并努力工作才能從源包構建 curl。
最新源碼如下圖:
2.2 編譯
解壓源碼壓縮包如下:
找到windows代碼工程文件,如下:
使用vs2017打開如下:
編譯后生成文件如下:
2.3 使用
使用步驟:
- 調(diào)用curl_global_init()初始化libcurl
- 調(diào)用curl_easy_init()函數(shù)得到 easy interface型指針
- 調(diào)用curl_easy_setopt()設置傳輸選項
- 根據(jù)curl_easy_setopt()設置的傳輸選項,實現(xiàn)回調(diào)函數(shù)以完成用戶特定任務
- 調(diào)用curl_easy_perform()函數(shù)完成傳輸任務
- 調(diào)用curl_easy_getinfo()接口獲取網(wǎng)絡請求響應信息,
- 調(diào)用curl_easy_cleanup()釋放內(nèi)存
- 調(diào)用curl_global_cleanup()析構libcurl
3、命令行測試
https://curl.se/docs/manual.html
3.1 獲取文件頭Headers
-H/--header LINE (H) # 添加請求頭, 可添加多個 -H 參數(shù),
# 參數(shù)格式: -H "NAME: VALUE"
-A/--user-agen STRING (H) # 請求頭的 User-Agent 字段
-e/--referer URL (H) # 請求頭的 Referer 字段
-r/--range RANGE (H) # 請求頭的 Range 字段
-b/--cookie STRING/FILE (H) # 請求頭的 Cookie 字段, 以字符串的形式提供,
# 或從指定 cookie 文件中讀取
-c/--cookie-jar FILE (H) # 把響應頭中的 cookie 保存到指定文件
-D/--dump-header FILE # 把 headers 信息保存指定文件
-I/--head # 只顯示文檔信息(只顯示響應頭)
3.2 請求內(nèi)容Request Content
# 執(zhí)行命令, 如果是 HTTP 則是請求方法, 如: GET, POST, PUT, DELETE 等
# 如果是 FTP 則是執(zhí)行 FTP協(xié)議命令
-X/--request COMMAND
# HTTP POST 請求內(nèi)容(并自動發(fā)出 POST 請求), 例如: aa=bb&cc=dd
-d/--data DATA (H)
# HTTP multipart POST 表單數(shù)據(jù),(并自動發(fā)出 POST 請求)
# 多個表單字段可添加多個 -H 參數(shù), 如果是文件參數(shù), 路徑值前面需要加@
# 參考格式: -F "name1=@/filepath" -F "name2=stringvalue"
-F/--form CONTENT (H)
3.3 響應內(nèi)容Response Content
-o/--output FILE FILE # 把響應內(nèi)容輸出到指定文件
-O/--remote-name # 以 URL 的文件名作為文件名稱保存響應內(nèi)容到當前目錄
-C/--continue-at OFFSET # 斷點續(xù)傳, 從 offset 位置繼續(xù)傳輸
3.4 GET請求
curl https://www.baidu.com/ # GET請求, 輸出 響應內(nèi)容
curl -I https://www.baidu.com/ # GET請求, 只輸出 響應頭
curl -i https://www.baidu.com/ # GET請求, 輸出 響應頭、響應內(nèi)容
curl -v https://www.baidu.com/ # GET請求, 輸出 通訊過程、頭部信息、響應內(nèi)容等
下載文件
# 指定保存的文件名稱下載文件
curl https://www.baidu.com -o baidu.txt
# 使用 URL 指定的資源文件名保存下載文件(URL 必須指向具體的文件名)
curl https://www.baidu.com/index.html -O
# 指定 Usaer-Agent 和 Referer 請求頭的值, 下載文件
curl -A "Mozilla/5.0 Chrome/70.0.3538.110 Safari/537.36" \
-e "https://www.baidu.com/" \
https://www.baidu.com/index.html -O
curl -o thatpage.html http://www.example.com/
curl -O http://www.example.com/index.html
curl -O www.haxx.se/index.html -O curl.se/download.html
# 指定Authorization請求頭的值, 下載文件
# 參數(shù)格式: -H "NAME: VALUE"
curl -H "Authorization: a112121dada" \
https://www.baidu.com/index.html -O
3.5 POST請求
POST 提交 JSON 數(shù)據(jù)(\表示命令語句還未結束, 換行繼續(xù))
curl -H "Content-Type: application/json" \
-d '{"username":"hello", "password":"123456"}' \
http://localhost/login
# POST 提交 表單數(shù)據(jù)
curl -F "username=hello" \
-F "password=123456" \
-F "head_image=@filepath.jpg" \
http://localhost/register
curl -d "name=Rafael%20Sagula&phone=3320780" http://www.where.com/guest.cgi
curl --data-urlencode "name=Rafael Sagula&phone=3320780" http://www.where.com/guest.cgi
curl -d "user=foobar&pass=12345&id=blablabla&ding=submit" http://www.formpost.com/getthis/post.cgi
curl -F "coolfiles=@fil1.gif;type=image/gif,fil2.txt,fil3.html" http://www.post.com/postit.cgi
3.6 其他
-h/--help # 打印幫助信息
-V/--version # 顯示版本信息
-s/--silent # 靜默模式, 不輸出任何內(nèi)容
-i/--include # 輸出包含 headers 信息
-v/--verbose # 輸出詳細內(nèi)容
-#/--progress-bar # 以進度條方式顯示傳輸過程
-y/--speed-time SECONDS # 連接 超時時間, 單位: 秒, 默認為 30
-m/--max-time SECONDS # 讀取 超時時間, 必須在該時間內(nèi)傳輸完數(shù)據(jù), 單位: 秒
--limit-rate RATE # 限速傳輸, 單位: Byte/s
-x/--proxy [PROTOCOL://]HOST[:PORT] # 設置代理
-U/--proxy-user USER[:PASSWORD] # 代理的用戶名和密碼
-u/--user USER[:PASSWORD][;OPTIONS] # 設置服務器的用戶密碼和登錄選項
--cacert FILE (SSL) # 使用指定的 CA 證書
-P/--ftp-port ADR (F) # 指定 FTP 傳輸?shù)亩丝?/span>
-T/--upload-file FILE # 上傳文件到指定的 URL (http/ftp) 位置,
# 參考格式: -T "file1" 或 -T "{file1,file2}"
-Q/--quote CMD (F/SFTP) # 執(zhí)行命令, -X 只執(zhí)行一條命令, -Q 可執(zhí)行多條,
# 多條命令將按順序執(zhí)行,
# 參考格式: -Q "cmd1" -Q "cmd2"
4、代碼測試
打開源碼的文件夾的測試示例子文件夾如下:
3.1 simple.c
/* <DESC>
* Download a given URL into a local file named page.out.
* </DESC>
*/
#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>
#include <curl/curl.h>
#pragma comment(lib, "libcurld.lib")
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/todos/2");
/* example.com is redirected, so we tell libcurl to follow redirection */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
/* 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);
}
return 0;
}
3.2 url2file.c
#include "pch.h"
#include <iostream>
/* <DESC>
* Download a given URL into a local file named page.out.
* </DESC>
*/
#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>
#include <curl/curl.h>
#pragma comment(lib, "libcurld.lib")
static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
size_t written = fwrite(ptr, size, nmemb, (FILE *)stream);
return written;
}
int main(int argc, char *argv[])
{
CURL *curl_handle;
static const char *pagefilename = "test.jpg";
FILE *pagefile;
if (argc < 2) {
printf("Usage: %s <URL>\n", argv[0]);
return 1;
}
curl_global_init(CURL_GLOBAL_ALL);
/* init the curl session */
curl_handle = curl_easy_init();
/* set URL to get here */
curl_easy_setopt(curl_handle, CURLOPT_URL, argv[1]);
/* Switch on full protocol/debug output while testing */
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
/* disable progress meter, set to 0L to enable it */
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);
/* send all data to this function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
/* open the file */
pagefile = fopen(pagefilename, "wb");
if (pagefile) {
/* write the page body to this file handle */
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, pagefile);
/* get it! */
curl_easy_perform(curl_handle);
/* close the header file */
fclose(pagefile);
}
/* cleanup curl stuff */
curl_easy_cleanup(curl_handle);
curl_global_cleanup();
return 0;
}
編譯如下:
運行如下:
下載圖片如下:
3.3 simplepost.c
/* <DESC>
* Very simple HTTP POST
* </DESC>
*/
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
static const char *postthis = "moo mooo moo moo";
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
/* if we do not provide POSTFIELDSIZE, libcurl will strlen() by
itself */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postthis));
/* 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);
}
return 0;
}
3.4 resolve.c
/* <DESC>
* Use CURLOPT_RESOLVE to feed custom IP addresses for given host name + port
* number combinations.
* </DESC>
*/
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res = CURLE_OK;
/* Each single name resolve string should be written using the format
HOST:PORT:ADDRESS where HOST is the name libcurl will try to resolve,
PORT is the port number of the service where libcurl wants to connect to
the HOST and ADDRESS is the numerical IP address
*/
struct curl_slist *host = curl_slist_append(NULL,
"example.com:443:127.0.0.1");
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_slist_free_all(host);
return (int)res;
}
3.5 progressfunc.c
/* <DESC>
* Use the progress callbacks, old and/or new one depending on available
* libcurl version.
* </DESC>
*/
#include <stdio.h>
#include <curl/curl.h>
#define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL 3000000
#define STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES 6000
struct myprogress {
curl_off_t lastruntime; /* type depends on version, see above */
CURL *curl;
};
/* this is how the CURLOPT_XFERINFOFUNCTION callback works */
static int xferinfo(void *p,
curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow)
{
struct myprogress *myp = (struct myprogress *)p;
CURL *curl = myp->curl;
curl_off_t curtime = 0;
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &curtime);
/* under certain circumstances it may be desirable for certain functionality
to only run every N seconds, in order to do this the transaction time can
be used */
if((curtime - myp->lastruntime) >= MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL) {
myp->lastruntime = curtime;
fprintf(stderr, "TOTAL TIME: %lu.%06lu\r\n",
(unsigned long)(curtime / 1000000),
(unsigned long)(curtime % 1000000));
}
fprintf(stderr, "UP: %lu of %lu DOWN: %lu of %lu\r\n",
(unsigned long)ulnow, (unsigned long)ultotal,
(unsigned long)dlnow, (unsigned long)dltotal);
if(dlnow > STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES)
return 1;
return 0;
}
int main(void)
{
CURL *curl;
CURLcode res = CURLE_OK;
struct myprogress prog;
curl = curl_easy_init();
if(curl) {
prog.lastruntime = 0;
prog.curl = curl;
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo);
/* pass the struct pointer into the xferinfo function */
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
res = curl_easy_perform(curl);
if(res != CURLE_OK)
fprintf(stderr, "%s\n", curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
return (int)res;
}
3.6 http-post.c
/* <DESC>
* simple HTTP POST using the easy interface
* </DESC>
*/
#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;
}
3.7 https.c
/* <DESC>
* Simple HTTPS GET
* </DESC>
*/
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
#ifdef SKIP_PEER_VERIFICATION
/*
* If you want to connect to a site who is not using a certificate that is
* signed by one of the certs in the CA bundle you have, you can skip the
* verification of the server's certificate. This makes the connection
* A LOT LESS SECURE.
*
* If you have a CA cert for the server stored someplace else than in the
* default bundle, then the CURLOPT_CAPATH option might come handy for
* you.
*/
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
#endif
#ifdef SKIP_HOSTNAME_VERIFICATION
/*
* If the site you are connecting to uses a different host name that what
* they have mentioned in their server certificate's commonName (or
* subjectAltName) fields, libcurl will refuse to connect. You can skip
* this check, but this will make the connection less secure.
*/
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
#endif
/* 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;
}
3.8 httpcustomheader.c
/* <DESC>
* HTTP request with custom modified, removed and added headers
* </DESC>
*/
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
struct curl_slist *chunk = NULL;
/* Remove a header curl would otherwise add by itself */
chunk = curl_slist_append(chunk, "Accept:");
/* Add a custom header */
chunk = curl_slist_append(chunk, "Another: yes");
/* Modify a header curl otherwise adds differently */
chunk = curl_slist_append(chunk, "Host: example.com");
/* Add a header with "blank" contents to the right of the colon. Note that
we are then using a semicolon in the string we pass to curl! */
chunk = curl_slist_append(chunk, "X-silly-header;");
/* set our custom set of headers */
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
curl_easy_setopt(curl, CURLOPT_URL, "localhost");
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
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 the custom headers */
curl_slist_free_all(chunk);
}
return 0;
}
3.9 getinfo.c
/* <DESC>
* Use getinfo to get content-type after completed transfer.
* </DESC>
*/
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://api.thecatapi.com/v1/images/search?limit=1");
res = curl_easy_perform(curl);
if(CURLE_OK == res) {
char *ct;
/* ask for the content-type */
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
if((CURLE_OK == res) && ct)
printf("We received Content-Type: %s\n", ct);
}
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
文章來源:http://www.zghlxwxcb.cn/news/detail-550553.html
3.10 getredirect.c
/* <DESC>
* Show how to extract Location: header and URL to redirect to.
* </DESC>
*/
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
char *location;
long response_code;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
/* example.com is redirected, figure out the redirection! */
/* 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));
else {
res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
if((res == CURLE_OK) &&
((response_code / 100) != 3)) {
/* a redirect implies a 3xx response code */
fprintf(stderr, "Not a redirect.\n");
}
else {
res = curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &location);
if((res == CURLE_OK) && location) {
/* This is the new absolute URL that you could redirect to, even if
* the Location: response header may have been a relative URL. */
printf("Redirected to: %s\n", location);
}
}
}
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
3.11 getreferrer.c
/* <DESC>
* Show how to extract referrer header.
* </DESC>
*/
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
curl = curl_easy_init();
if(curl) {
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
curl_easy_setopt(curl, CURLOPT_REFERER, "https://example.org/referrer");
/* 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));
else {
char *hdr;
res = curl_easy_getinfo(curl, CURLINFO_REFERER, &hdr);
if((res == CURLE_OK) && hdr)
printf("Referrer header: %s\n", hdr);
}
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
3.12 執(zhí)行HTTP的GET請求
#include <stdio.h>
#include <curl/curl.h>
#include <string>
size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
((std::string*)userdata)->append(ptr, nmemb);
return nmemb;
}
int main(void)
{
curl_global_init(CURL_GLOBAL_DEFAULT);
CURL* curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, "https://www.baidu.com");
// no certificate, not verify server certificate
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
std::string response_data;
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_data);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
else
{
long response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
printf("response code %d \n", response_code);
printf("response data : \n ");
printf(response_data.c_str());
}
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
3.13 執(zhí)行HTTP的POST請求
#include <stdio.h>
#include <curl/curl.h>
#include <string>
size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
((std::string*)userdata)->append(ptr, nmemb);
return nmemb;
}
int main(int argc, void* argv)
{
curl_global_init(CURL_GLOBAL_DEFAULT);
CURL* curl = curl_easy_init();
if (curl)
{
// set url
curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts");
// no certificate, not verify server certificate
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
// set http method
curl_easy_setopt(curl, CURLOPT_POST, 1);
// set header
struct curl_slist * slist = nullptr;
slist = curl_slist_append(slist, "Content-Type : application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
// set body
std::string body = "{\
\"title\":\"libcurl post title\",\
\"body\" : \"libcurl post body\",\
\"userId\" : 1}";
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
// set response callback to read response
std::string response_data;
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_data);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
else
{
// get response code
long response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
printf("response code %d \n", response_code);
printf("response data : \n ");
printf(response_data.c_str());
}
curl_slist_free_all(slist);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
3.14 獲取HTTP報頭提取Cookie信息
static size_t writeResponse(void *ptr, size_t size, size_t nmemb, void *userData)
{
std::string* pBuffer = (std::string*)userData;
size_t length = size * nmemb;
pBuffer->append((char*)ptr, length);
return length;
}
int getCookiesData()
{
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_URL, "http://127.0.0.1/login");
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "cache-control: no-cache");
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "username=slny001&password=Hx%40kj%2319&loginType=2&undefined=");
std::string strResponse;
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, Writeresponse);//設置回調(diào)函數(shù) //curl_easy_setopt(pCurlHandle, CURLOPT_HEADER, 1);//保存HTTP頭部信息到strResponseData
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &strResponse);//設置回調(diào)函數(shù)的參數(shù),獲取反饋信息
curl_easy_setopt(hnd, CURLOPT_HEADERFUNCTION, Writeresponse);//設置回調(diào)函數(shù):輸出response headers
string responseHeadBuffer;
curl_easy_setopt(hnd, CURLOPT_HEADERDATA, &responseHeadBuffer);//設置回調(diào)函數(shù)參數(shù)
CURLcode ret = curl_easy_perform(hnd);
if (0 == ret)
{
int nPosOfCookie = responseHeadBuffer.find("Cookie: ", 0);
if (nPosOfCookie > 0)
{
int nPosOfEndCookie = responseHeadBuffer.find(";", nPosOfCookie);
m_cookie = responseHeadBuffer.substr(nPosOfCookie + 7, nPosOfEndCookie - nPosOfCookie - 7);
}
}
curl_slist_free_all(headers);
curl_easy_cleanup(hnd);
return 0;
}
3.15 復雜示例
#define CURL_STATICLIB //如果是靜態(tài)庫方式,需要包含這句
#include "curl\curl.h"
#include <iostream>
#include <list>
#include <string>
#ifdef _DEBUG
#pragma comment(lib,"libcurld.lib")
#else
#pragma comment(lib,"libcurl.lib")
#endif
#pragma comment ( lib, "ws2_32.lib" )
#pragma comment ( lib, "winmm.lib" )
#pragma comment ( lib, "wldap32.lib" )
#pragma comment(lib, "Advapi32.lib")
std::wstring AsciiToUnicode(const std::string& str)
{
// 預算-緩沖區(qū)中寬字節(jié)的長度
int unicodeLen = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, nullptr, 0);
// 給指向緩沖區(qū)的指針變量分配內(nèi)存
wchar_t *pUnicode = (wchar_t*)malloc(sizeof(wchar_t)*unicodeLen);
// 開始向緩沖區(qū)轉(zhuǎn)換字節(jié)
MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, pUnicode, unicodeLen);
std::wstring ret_str = pUnicode;
free(pUnicode);
return ret_str;
}
std::string UnicodeToUtf8(const std::wstring& wstr)
{
// 預算-緩沖區(qū)中多字節(jié)的長度
int ansiiLen = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
// 給指向緩沖區(qū)的指針變量分配內(nèi)存
char *pAssii = (char*)malloc(sizeof(char)*ansiiLen);
// 開始向緩沖區(qū)轉(zhuǎn)換字節(jié)
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, pAssii, ansiiLen, nullptr, nullptr);
std::string ret_str = pAssii;
free(pAssii);
return ret_str;
}
//ANSI轉(zhuǎn)UTF8
std::string AsciiToUtf8(const std::string& str)
{
return UnicodeToUtf8(AsciiToUnicode(str));
}
//UTF8轉(zhuǎn)ANSI
std::string Utf8toAscii(const std::string strUTF8)
{
std::string strAnsi = "";
//獲取轉(zhuǎn)換為多字節(jié)后需要的緩沖區(qū)大小,創(chuàng)建多字節(jié)緩沖區(qū)
UINT nLen = MultiByteToWideChar(CP_UTF8, NULL, strUTF8.c_str(), -1, NULL, NULL);
WCHAR *wszBuffer = new WCHAR[nLen + 1];
nLen = MultiByteToWideChar(CP_UTF8, NULL, strUTF8.c_str(), -1, wszBuffer, nLen);
wszBuffer[nLen] = 0;
nLen = WideCharToMultiByte(936, NULL, wszBuffer, -1, NULL, NULL, NULL, NULL);
CHAR *szBuffer = new CHAR[nLen + 1];
nLen = WideCharToMultiByte(936, NULL, wszBuffer, -1, szBuffer, nLen, NULL, NULL);
szBuffer[nLen] = 0;
strAnsi = szBuffer;
//清理內(nèi)存
delete[]szBuffer;
delete[]wszBuffer;
return strAnsi;
}
// reply of the requery
size_t req_reply(void *ptr, size_t size, size_t nmemb, void *stream)
{
if (stream == NULL || ptr == NULL || size == 0)
return 0;
size_t realsize = size * nmemb;
std::string *buffer = (std::string*)stream;
if (buffer != NULL)
{
buffer->append((const char *)ptr, realsize);
}
return realsize;
/*
std::string *str = (std::string*)stream;
(*str).append((char*)ptr, size*nmemb);
return size * nmemb;
*/
}
/*
功能:get http數(shù)據(jù)
參數(shù):url:請求字符串。如果請求帶參數(shù)數(shù)據(jù),直接拼湊到url后面;比如:http://127.0.0.1:8080/api/Accounts/Login?uername=admin&password=123
listRequestHeader:請求頭數(shù)據(jù)列表。
bResponseIsWithHeaderData:bool類型,表示響應體中是否包含應答頭數(shù)據(jù)。true,包含,false,不包含。如果包含的話,應答數(shù)據(jù)中包含Content-Type,Server等信息。
nConnectTimeout:連接超時時間,單位為秒;
nTimeout:讀寫數(shù)據(jù)超時時間,單位為秒
返回值:CURLcode
*/
CURLcode curl_get_req(const std::string &url, std::string &response, std::list<std::string> listRequestHeader, bool bResponseIsWithHeaderData = false, int nConnectTimeout = 10, int nTimeout = 10)
{
// init curl
CURL *curl = curl_easy_init();
// res code
CURLcode res;
if (curl)
{
// set params
curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // url
//curl_easy_setopt(m_curl, CURLOPT_PORT, 8089); //port
curl_easy_setopt(curl, CURLOPT_POST, 0); // get reqest
//構建HTTP報文頭
struct curl_slist* headers = NULL;
if (listRequestHeader.size() > 0)
{
std::list<std::string>::iterator iter, iterEnd;
iter = listRequestHeader.begin();
iterEnd = listRequestHeader.end();
for (iter; iter != iterEnd; iter++)
{
headers = curl_slist_append(headers, iter->c_str());
}
//headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");
//headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
if (headers != NULL)
{
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//設置http請求頭信息
}
}
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
if (bResponseIsWithHeaderData)
{
curl_easy_setopt(curl, CURLOPT_HEADER, 1);//響應體中是否包含了頭信息,比如Content-Type:application/json;charset=UTF-8
}
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, nConnectTimeout); // set transport and time out time
curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeout);
// start request
res = curl_easy_perform(curl);
if (headers != NULL)
{
curl_slist_free_all(headers); //free the list again
}
}
// release curl
curl_easy_cleanup(curl);
return res;
}
CURLcode curl_get_req_ex(CURL *curl, const std::string &url, std::string &response, std::list<std::string> listRequestHeader, bool bResponseIsWithHeaderData = false, int nConnectTimeout = 10, int nTimeout = 10)
{
// res code
CURLcode res;
if (curl)
{
// set params
curl_easy_reset(curl);
/* enable TCP keep-alive for this transfer */
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
/* keep-alive idle time to 120 seconds */
curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
/* interval time between keep-alive probes: 30 seconds */
curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 30L);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // url
//curl_easy_setopt(m_curl, CURLOPT_PORT, 8089); //port
curl_easy_setopt(curl, CURLOPT_POST, 0); // get reqest
//構建HTTP報文頭
struct curl_slist* headers = NULL;
if (listRequestHeader.size() > 0)
{
std::list<std::string>::iterator iter, iterEnd;
iter = listRequestHeader.begin();
iterEnd = listRequestHeader.end();
for (iter; iter != iterEnd; iter++)
{
headers = curl_slist_append(headers, iter->c_str());
}
//headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");
//headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
if (headers != NULL)
{
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//設置http請求頭信息
}
}
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
if (bResponseIsWithHeaderData)
{
curl_easy_setopt(curl, CURLOPT_HEADER, 1);//響應體中是否包含了頭信息,比如Content-Type:application/json;charset=UTF-8
}
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, nConnectTimeout); // set transport and time out time
curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeout);
// start request
res = curl_easy_perform(curl);
if (headers != NULL)
{
curl_slist_free_all(headers); //free the list again
}
}
return res;
}
/*
功能:post http數(shù)據(jù)
參數(shù):url:請求字符串,比如:http://127.0.0.1:8080/api/Accounts/Login
postParams:請求附帶的參數(shù),比如uername=admin&password=123
listRequestHeader:請求頭數(shù)據(jù)列表。
bResponseIsWithHeaderData:bool類型,表示響應體中是否包含應答頭數(shù)據(jù)。true,包含,false,不包含。如果包含的話,應答數(shù)據(jù)中包含Content-Type,Server等信息。
nConnectTimeout:連接超時時間,單位為秒;
nTimeout:讀寫數(shù)據(jù)超時時間,單位為秒
返回值:CURLcode
*/
CURLcode curl_post_req(const std::string &url, const std::string &postParams, std::string &response, std::list<std::string> listRequestHeader, bool bResponseIsWithHeaderData = false, int nConnectTimeout = 10, int nTimeout = 10)
{
// init curl
CURL *curl = curl_easy_init();
// res code
CURLcode res;
if (curl)
{
// set params
curl_easy_setopt(curl, CURLOPT_POST, 1); // post req
curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // url
//curl_easy_setopt(m_curl, CURLOPT_PORT, 8089); //port
curl_easy_setopt(curl, CURLOPT_POST, 1); // post reqest
//構建HTTP報文頭
struct curl_slist* headers = NULL;
if (listRequestHeader.size() > 0)
{
std::list<std::string>::iterator iter, iterEnd;
iter = listRequestHeader.begin();
iterEnd = listRequestHeader.end();
for (iter; iter != iterEnd; iter++)
{
headers = curl_slist_append(headers, iter->c_str());
}
//headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");
//headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
if (headers != NULL)
{
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//設置http請求頭信息
}
}
else
{
headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
if (headers != NULL)
{
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//設置http請求頭信息
}
}
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postParams.c_str()); // params
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //返回的頭部中有Location(一般直接請求的url沒找到),則繼續(xù)請求Location對應的數(shù)據(jù)
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
if (bResponseIsWithHeaderData)
{
curl_easy_setopt(curl, CURLOPT_HEADER, 1);//響應體中是否包含了頭信息,比如Content-Type:application/json;charset=UTF-8
}
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, nConnectTimeout);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeout);
// start request
res = curl_easy_perform(curl);
if (headers != NULL)
{
curl_slist_free_all(headers); //free the list again
}
}
// release curl
curl_easy_cleanup(curl);
return res;
}
CURLcode curl_post_req_ex(CURL *curl, const std::string &url, const std::string &postParams, std::string &response, std::list<std::string> listRequestHeader, bool bResponseIsWithHeaderData = false, int nConnectTimeout = 10, int nTimeout = 10)
{
// res code
CURLcode res;
if (curl)
{
// set params
curl_easy_reset(curl);
/* enable TCP keep-alive for this transfer */
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
/* keep-alive idle time to 120 seconds */
curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
/* interval time between keep-alive probes: 30 seconds */
curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 30L);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // url
//curl_easy_setopt(m_curl, CURLOPT_PORT, 8089); //port
curl_easy_setopt(curl, CURLOPT_POST, 1); // post reqest
//構建HTTP報文頭
struct curl_slist* headers = NULL;
if (listRequestHeader.size() > 0)
{
std::list<std::string>::iterator iter, iterEnd;
iter = listRequestHeader.begin();
iterEnd = listRequestHeader.end();
for (iter; iter != iterEnd; iter++)
{
headers = curl_slist_append(headers, iter->c_str());
}
//headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");
//headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded;charset=UTF-8");
if (headers != NULL)
{
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//設置http請求頭信息
}
}
else
{
headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
if (headers != NULL)
{
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//設置http請求頭信息
}
}
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postParams.c_str()); // params
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //返回的頭部中有Location(一般直接請求的url沒找到),則繼續(xù)請求Location對應的數(shù)據(jù)
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
if (bResponseIsWithHeaderData)
{
curl_easy_setopt(curl, CURLOPT_HEADER, 1);//響應體中是否包含了頭信息,比如Content-Type:application/json;charset=UTF-8
}
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, nConnectTimeout);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeout);
// start request
res = curl_easy_perform(curl);
if (headers != NULL)
{
curl_slist_free_all(headers); //free the list again
}
}
return res;
}
//實例1
void test1()
{
curl_global_init(CURL_GLOBAL_ALL);
//post獲取數(shù)據(jù)
std::string strResponse = "",strResponseAnsi = "";
strResponse.clear();
CURLcode res = curl_post_req("http://127.0.0.1:8080/api/Accounts/Login", "username=admin&password=123", strResponse);
if (res == CURLE_OK)
{
std::string strToken = "";
strResponseAnsi = Utf8toAscii(strResponse);
}
//get獲取數(shù)據(jù)
strResponse.clear();
res = curl_get_req("http://127.0.0.1:8080/api/Accounts/Login?username=admin&password=123", strResponse);
if (res == CURLE_OK)
{
int jj = 0;
}
curl_global_cleanup();
}
//實例2
void test1()
{
//post json數(shù)據(jù)
CURL * curl = curl_easy_init();
std::string strResponse = "", strResponseAnsi = "";
char szRequestUrl[256] = { 0 };
CURLcode res = CURLE_OK;
sprintf_s(szRequestUrl, "%s/api/GPS/AddOne", "http://127.0.0.1:8080");
std::string strPostParams = "";
try
{
boost::property_tree::ptree ptroot;
ptroot.put("deviceid", "12345678");
ptroot.put<unsigned int>("deviceStatus", 0);
ptroot.put<unsigned int>("alarmFlag", 0);
ptroot.put("lng", fLongitude);
ptroot.put("lat", fLatitude);
ptroot.put("speed", 0);
ptroot.put("direction", 0);
ptroot.put<int>("altitude", 10);
ptroot.put("gpsTime", "2018-10-10 12:00:01");
std::stringstream sstream;
boost::property_tree::write_json(sstream, ptroot);
strPostParams = sstream.str();
bSuccess = true;
}
catch (boost::property_tree::ptree_error pt)
{
pt.what();
}
if (bSuccess)
{
std::string strAuthorization = "admin---";
std::string strRequestHeaders = strAuthorization;
std::list<std::string> listRequestHeader;
listRequestHeader.push_back(strRequestHeaders);
listRequestHeader.push_back("Content-Type:application/json;charset=UTF-8");
res = curl_post_req_ex(curl, szRequestUrl, strPostParams, strResponse, listRequestHeader);
if (res == CURLE_OK)
{
bSuccess = true;
}
}
curl_easy_cleanup(curl);
}
void main()
{
test1();
test2();
}
結語
如果您覺得該方法或代碼有一點點用處,可以給作者點個贊,或打賞杯咖啡;
╮( ̄▽ ̄)╭如果您感覺方法或代碼不咋地
//(ㄒoㄒ)//,就在評論處留言,作者繼續(xù)改進;
o_O???如果您需要相關功能的代碼定制化開發(fā),可以留言私信作者;
(????)感謝各位大佬童鞋們的支持!
( ′ ▽′ )? ( ′ ▽′)っ?。?!文章來源地址http://www.zghlxwxcb.cn/news/detail-550553.html
到了這里,關于【小沐學C++】libcurl實現(xiàn)HTTP/HTTPS請求的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!