C++中LibCurl庫的使用教程分享
LibCurl是一個開源的免費的多協(xié)議數(shù)據(jù)傳輸開源庫,該框架具備跨平臺性,開源免費,并提供了包括HTTP、FTP、SMTP、POP3等協(xié)議的功能,使用libcurl可以方便地進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)傳輸操作,如發(fā)送HTTP請求、下載文件、發(fā)送電子郵件等。它被廣泛應(yīng)用于各種網(wǎng)絡(luò)應(yīng)用開發(fā)中,特別是涉及到數(shù)據(jù)傳輸?shù)膱鼍啊?/p>
下載地址:https://curl.haxx.se/download.html
首先讀者需要自行下載該庫,如下筆者選擇下載curl-8.0.1.zip這個源代碼版本,讀者可找到如下頁面,并點擊對應(yīng)版本完成下載,當(dāng)下載好以后讀者可自行將其解壓縮到任意目錄下。

當(dāng)讀者解壓縮后,可打開VS2013 開發(fā)人員命令提示并切換帶該目錄中的curl-8.0.1\winbuild目錄,通過執(zhí)行如下兩條命令即可分別實現(xiàn)編譯靜態(tài)庫或動態(tài)庫,我們以靜態(tài)庫編譯為主,執(zhí)行如下命令讀者可自行等待一段時間。
- 動態(tài)庫: nmake /f Makefile.vc mode=dll VC=13 MACHINE=x86 DEBUG=no
- 靜態(tài)庫: nmake / f Makefile.vc mode = static VC = 13 ENABLE_IDN = no MACHINE = x86 DEBUG = no
這個庫在編譯通過后會自動生成文件到builds\libcurl-vc13-x86-release-static-ipv6-sspi-schannel目錄內(nèi),讀者可自行打開該目錄,即可看到該目錄內(nèi)的頭文件以及庫目錄文件,如下圖所示;

讀者可自行配置這個靜態(tài)庫,通常只需要配置include和lib文件即可,該庫的使用很簡單,首先我們需要調(diào)用curl_easy_init()函數(shù)對CURL對象進(jìn)行初始化,接著通過調(diào)用curl_easy_setopt()并傳入一個訪問URL鏈接,當(dāng)訪問成功后則可調(diào)用curl_easy_perform()函數(shù)得到訪問結(jié)果,這就是該庫基本使用方法,如下代碼。
#define CURL_STATICLIB
#define BUILDING_LIBCURL
#include <iostream>
#include "curl/curl.h"
#pragma comment (lib,"libcurl_a.lib")
#pragma comment (lib,"wldap32.lib")
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"Crypt32.lib")
using namespace std;
int main(int argc, char *argv[])
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, "https://www.lyshark.com");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
std::cout << "返回狀態(tài): " << res << std::endl;
system("pause");
return 0;
}運行上述代碼,讀者可看到網(wǎng)站www.lyshark.com的源代碼,如下圖所示;

上述代碼中的curl_easy_setopt()函數(shù)第二個參數(shù)可以使用多種類型的變量定義,我們可以通過傳入不同的常量來定義請求頭中的參數(shù),例如當(dāng)我們需要修改協(xié)議頭時,可以使用CURLOPT_HTTPHEADER常量,并在其后第三個參數(shù)中傳入該常量所對應(yīng)的結(jié)構(gòu)即可,這個結(jié)構(gòu)體定義有許多類型,具體如下下表所示;
| 常量名稱 | 描述 |
|---|---|
| CURLINFO_EFFECTIVE_URL | 最后一個有效的URL地址 |
| CURLINFO_HTTP_CODE | 最后一個收到的HTTP代碼 |
| CURLINFO_FILETIME | 遠(yuǎn)程獲取文檔的時間,如果無法獲取,則返回值為-1 |
| CURLINFO_TOTAL_TIME | 最后一次傳輸所消耗的時間 |
| CURLINFO_NAMELOOKUP_TIME | 名稱解析所消耗的時間 |
| CURLINFO_CONNECT_TIME | 建立連接所消耗的時間 |
| CURLINFO_PRETRANSFER_TIME | 從建立連接到準(zhǔn)備傳輸所使用的時間 |
| CURLINFO_STARTTRANSFER_TIME | 從建立連接到傳輸開始所使用的時間 |
| CURLINFO_REDIRECT_TIME | 在事務(wù)傳輸開始前重定向所使用的時間 |
| CURLINFO_SIZE_UPLOAD | 以字節(jié)為單位返回上傳數(shù)據(jù)量的總值 |
| CURLINFO_SIZE_DOWNLOAD | 以字節(jié)為單位返回下載數(shù)據(jù)量的總值 |
| CURLINFO_SPEED_DOWNLOAD | 平均下載速度 |
| CURLINFO_SPEED_UPLOAD | 平均上傳速度 |
| CURLINFO_HEADER_SIZE | header部分的大小 |
| CURLINFO_HEADER_OUT | 發(fā)送請求的字符串 |
| CURLINFO_REQUEST_SIZE | 在HTTP請求中有問題的請求的大小 |
| CURLINFO_SSL_VERIFYRESULT | 通過設(shè)置CURLOPT_SSL_VERIFYPEER返回的SSL證書驗證請求的結(jié)果 |
| CURLINFO_CONTENT_LENGTH_DOWNLOAD | 從Content-Length: field中讀取的下載內(nèi)容長度 |
| CURLINFO_CONTENT_LENGTH_UPLOAD | 上傳內(nèi)容大小的說明 |
| CURLINFO_CONTENT_TYPE | 下載內(nèi)容的Content-Type:值,NULL表示服務(wù)器沒有發(fā)送有效的Content-Type:header |
如下案例是一個簡單的GET請求封裝,通過調(diào)用GetStatus()函數(shù)實現(xiàn)對特定頁面發(fā)起請求的功能,其中curl_slist_append()用于增加新的請求頭數(shù)據(jù),在調(diào)用curl_easy_setopt()函數(shù)時,分別傳入了CURLOPT_HTTPHEADER設(shè)置請求頭,CURLOPT_WRITEFUNCTION設(shè)置回調(diào),CURLINFO_PRIMARY_IP獲取目標(biāo)IP地址,CURLINFO_RESPONSE_CODE獲取目標(biāo)返回代碼,此處的write_data()函數(shù)直接返回0則表示屏蔽所有的頁面輸出內(nèi)容。
#define CURL_STATICLIB
#define BUILDING_LIBCURL
#include <iostream>
#include "curl/curl.h"
#pragma comment (lib,"libcurl_a.lib")
#pragma comment (lib,"wldap32.lib")
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"Crypt32.lib")
using namespace std;
// 設(shè)置CURLOPT_WRITEFUNCTION回調(diào)函數(shù),返回為空屏蔽輸出
static size_t write_data(char *d, size_t n, size_t l, void *p)
{
return 0;
}
// 獲取網(wǎng)站返回值
void GetStatus(char *UrlPage)
{
CURLcode return_code;
// 初始化模塊
return_code = curl_global_init(CURL_GLOBAL_WIN32);
if (CURLE_OK != return_code)
{
return;
}
// 初始化填充請求頭
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0)");
headers = curl_slist_append(headers, "Referer: https://www.lyshark.com");
// 初始化請求庫
CURL *easy_handle = curl_easy_init();
if (NULL != easy_handle)
{
// CURLOPT_HTTPHEADER 自定義設(shè)置請求頭
curl_easy_setopt(easy_handle, CURLOPT_HTTPHEADER, headers);
// CURLOPT_URL 自定義請求的網(wǎng)站
curl_easy_setopt(easy_handle, CURLOPT_URL, UrlPage);
// CURLOPT_WRITEFUNCTION 設(shè)置回調(diào)函數(shù),屏蔽輸出
curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data);
// 執(zhí)行CURL訪問網(wǎng)站
return_code = curl_easy_perform(easy_handle);
char *ipAddress = { 0 };
// CURLINFO_PRIMARY_IP 獲取目標(biāo)IP信息
return_code = curl_easy_getinfo(easy_handle, CURLINFO_PRIMARY_IP, &ipAddress);
if ((CURLE_OK == return_code) && ipAddress)
{
std::cout << "目標(biāo)IP: " << ipAddress << std::endl;
}
long retcode = 0;
// CURLINFO_RESPONSE_CODE 獲取目標(biāo)返回狀態(tài)
return_code = curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE, &retcode);
if ((CURLE_OK == return_code) && retcode)
{
std::cout << "返回狀態(tài)碼: " << retcode << std::endl;
}
}
curl_easy_cleanup(easy_handle);
curl_global_cleanup();
}
int main(int argc, char *argv[])
{
GetStatus("https://www.lyshark.com");
system("pause");
return 0;
}運行上述代碼,則可以獲取到www.lyshark.com目標(biāo)主機(jī)的IP地址以及頁面返回狀態(tài),如下圖所示;

當(dāng)然該庫同樣支持POST請求方式,在使用POST請求時我們可以通過CURLOPT_COOKIEFILE參數(shù)指定Cookie參數(shù),通過CURLOPT_POSTFIELDS指定POST的數(shù)據(jù)集,而如果需要使用代理模式則可以通過CURLOPT_PROXY方式來指定代理地址,
#define CURL_STATICLIB
#define BUILDING_LIBCURL
#include <iostream>
#include "curl/curl.h"
#pragma comment (lib,"libcurl_a.lib")
#pragma comment (lib,"wldap32.lib")
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"Crypt32.lib")
using namespace std;
bool SendPost(char *Url, char *Cookie, char *PostVal)
{
CURL *curl;
CURLcode res;
// 初始化庫
curl = curl_easy_init();
if (curl)
{
// 設(shè)置請求頭
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0)");
headers = curl_slist_append(headers, "Referer: https://www.lyshark.com");
// 設(shè)置請求頭
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// 指定URL
curl_easy_setopt(curl, CURLOPT_URL, Url);
// 指定cookie參數(shù)
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, Cookie);
// 指定post內(nèi)容
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, PostVal);
// 是否代理
// curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return true;
}
int main(int argc, char *argv[])
{
// 傳入網(wǎng)址 cookie 以及post參數(shù)
SendPost("https://www.lyshark.com/post.php", "1e12sde342r2", "&logintype=uid&u=xieyan&psw=xxx86");
system("pause");
return 0;
}該函數(shù)的調(diào)用需要有一個POST結(jié)構(gòu)才可測試,此處由于我并沒有指定接口所有返回了頁面錯誤信息,如下圖所示;

接著繼續(xù)實現(xiàn)下載頁面到本地的功能,該功能實現(xiàn)的原理是利用write_data回調(diào)函數(shù),當(dāng)頁面數(shù)據(jù)被讀入到內(nèi)存時回調(diào)函數(shù)會被觸發(fā),在該回調(diào)函數(shù)的內(nèi)部通過調(diào)用fwrite函數(shù)將ptr指針中的數(shù)據(jù)保存本地,實現(xiàn)這段代碼如下所示;
#define CURL_STATICLIB
#define BUILDING_LIBCURL
#include <iostream>
#include "curl/curl.h"
#pragma comment (lib,"libcurl_a.lib")
#pragma comment (lib,"wldap32.lib")
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"Crypt32.lib")
using namespace std;
FILE *fp;
size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
int written = fwrite(ptr, size, nmemb, (FILE *)fp);
return written;
}
BOOL GetUrl(char *URL, char *FileName)
{
CURL *curl;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, URL);
// 在屏幕打印請求連接過程和返回http數(shù)據(jù)
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// 查找次數(shù),防止查找太深
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 1);
// 設(shè)置連接超時
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
// 接收數(shù)據(jù)時超時設(shè)置
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
if ((fp = fopen(FileName, "w")) == NULL)
{
curl_easy_cleanup(curl);
return FALSE;
}
// CURLOPT_WRITEFUNCTION 將后繼的動作交給write_data函數(shù)處理
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
return TRUE;
}
int main(int argc, char *argv[])
{
// 下載網(wǎng)頁到本地
GetUrl("https://www.lyshark.com", "./lyshark.html");
system("pause");
return 0;
}當(dāng)讀者運行上述程序后,即可將www.lyshark.com網(wǎng)站頁面源碼,下載到本地當(dāng)前目錄下lyshark.html,輸出效果如下圖所示;

為了能解析參數(shù),我們還是需要將頁面源代碼讀入到內(nèi)存中,要實現(xiàn)這個需求并不難,首先我們定義一個std::string容器,然后當(dāng)有新數(shù)據(jù)產(chǎn)生時觸發(fā)WriteCallback在該函數(shù)內(nèi),我們直接將數(shù)據(jù)拷貝到一個內(nèi)存指針中,也就是存儲到read_buffer內(nèi),并將該緩沖區(qū)返回給調(diào)用者即可,如下則是完整源代碼。
#define CURL_STATICLIB
#define BUILDING_LIBCURL
#include <iostream>
#include <string>
#include "curl/curl.h"
#pragma comment (lib,"libcurl_a.lib")
#pragma comment (lib,"wldap32.lib")
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"Crypt32.lib")
using namespace std;
// 存儲回調(diào)函數(shù)
size_t WriteCallback(char *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
// 獲取數(shù)據(jù)并放入string中.
std::string GetUrlPageOfString(std::string url)
{
std::string read_buffer;
CURL *curl;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl)
{
// 忽略證書檢查
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
// 重定向
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
// URL路徑
curl_easy_setopt(curl, CURLOPT_URL, url);
// 查找次數(shù),防止查找太深
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 1);
// 連接超時
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
// 接收數(shù)據(jù)時超時設(shè)置
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
// 寫入回調(diào)函數(shù)
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &read_buffer);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
return read_buffer;
}
return "None";
}
int main(int argc, char *argv[])
{
std::string urls = GetUrlPageOfString("https://www.lyshark.com");
std::cout << "接收長度: " << urls.length() << " bytes" << std::endl;
system("pause");
return 0;
}如下圖所示,則是運行后輸出內(nèi)存數(shù)據(jù)長度,當(dāng)然我們也可以直接輸出urls中的數(shù)據(jù),也就是網(wǎng)頁的源代碼;

到此這篇關(guān)于C++中LibCurl庫的使用教程分享的文章就介紹到這了,更多相關(guān)C++ LibCurl內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C/C++實現(xiàn)枚舉網(wǎng)上鄰居信息的示例詳解
在Windows系統(tǒng)中,通過網(wǎng)絡(luò)鄰居可以方便地查看本地網(wǎng)絡(luò)中的共享資源和計算機(jī),本文將介紹一個簡單的C++程序,使用Windows API枚舉網(wǎng)絡(luò)鄰居信息,并獲取對端名稱、本機(jī)名稱、主機(jī)名稱以及主機(jī)IP等信息,文中通過代碼示例給大家講解非詳細(xì),需要的朋友可以參考下2023-12-12
C語言結(jié)構(gòu)體(struct)常見使用方法(細(xì)節(jié)問題)
這篇文章主要介紹了C語言結(jié)構(gòu)體(struct)常見使用方法(細(xì)節(jié)問題),需要的朋友可以參考下2017-03-03

