Using libcurl in VC++
curl是瑞典curl組織開發(fā)的,Official Website:
Introduction
curl是一個(gè)基于命令行的應(yīng)用工具,提供利用URL標(biāo)準(zhǔn)進(jìn)行文件傳輸?shù)墓δ堋?/p>
目前已經(jīng)支持非常多的流行的互聯(lián)網(wǎng)協(xié)議,如:FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS and FILE等。curl支持SSL認(rèn)證,HTTP POST/PUT,FTP上傳,HTTP上傳、代理、cookies、用戶+密碼認(rèn)證、文件續(xù)傳、代理管道等一系列強(qiáng)大功能。
curl是用C語言寫的,但是綁定了很多開發(fā)語言。大體上可以把curl分成命令行工具和libcurl庫兩個(gè)部分,命令行工具可以直接輸入指令完成相應(yīng)功能,libcurl則是一個(gè)客戶端URL傳輸庫,是線程安全且兼容IPv6,可以非常方便地用來做相關(guān)開發(fā)。
How to Using Curl Lib:
Compile curl without openssl and zlib.
?Step1:下載CURL 最近的幾個(gè)版本,我是curl-7.21.5。然后解壓到curl-7.21.5文件夾。
Step2:打開curl-7.21.5文件夾,找到vc6curl.dsw。就是VC6工程的文件。
Step3:用2008打開,選擇 生成(B)-》生成解決方案(F7) ,不要點(diǎn)三角形那個(gè)啟動(dòng)調(diào)試
Step4:打開curl-7.21.5\lib\DLL-Debug 找到libcurld.dll和libcurld_imp.lib。
Step5:打開curl-7.21.5\include\找到curl文件和第四步找到的libcurld.dll和libcurld_imp.lib一起放到你新建的工程目錄你。比如你新建了個(gè)名為:DDDDDD的工程,那么久把他們放到\Visual Studio 2008\Projects\DDDDDD\DDDDDD就是有很多.h 和。CPP的地方
Step6:在你工程MAIN函數(shù)前面 include"curl/curl.h" 不行的話就用include<curl/curl.h>
Step7:VS2008編代碼的左邊,在工程DDDDDD就是頭文件上方右擊屬性-》配置屬性-》鏈接器-》命令行有個(gè)附加選項(xiàng)那打入libcurld_imp.lib就OK了
? 如果運(yùn)行提示缺少libsasl.dll,就下個(gè)SVN,在安裝目錄下的bin目錄下找到libsasl.dll,復(fù)制到工程目錄下即可
基于libcurl庫的開發(fā)(Windows平臺(tái),MSVC2010開發(fā)環(huán)境)。
libcurl是一個(gè)簡(jiǎn)單易用的基于URL傳輸?shù)目蛻舳碎_發(fā)庫,支持多種平臺(tái)以及三十多種開發(fā)語言綁定。libcurl是線程安全的,兼容IPv6,功能強(qiáng)大且運(yùn)行效率高。
在10環(huán)境中做libcurl開發(fā),需要將靜態(tài)庫文件加到編譯鏈接環(huán)境中,并且要dll動(dòng)態(tài)運(yùn)行庫支持。
libcurl提供了一組C語言API函數(shù)直接調(diào)用。首先需要提到的兩個(gè)函數(shù)就是curl_global_init()和curl_global_cleanup()。libcurl要用到一系列的全局常量,curl_global_init()函數(shù)就是初始化這些變量,并分配一些全局資源;curl_global_cleanup()則負(fù)責(zé)釋放這些資源。因此一般情況下,在調(diào)用libcurl函數(shù)之前,先用curl_global_init(CURL_GLOBAL_ALL)做初始化,在調(diào)用完畢后,用curl_global_cleanup()
退出。需要注意的是,這些全局變量和資源并不是線程安全的,因此,在多線程應(yīng)用的環(huán)境中,最好不要多次調(diào)用curl_global_init()和curl_global_cleanup(),調(diào)用其他函數(shù)并不會(huì)改變這些全局變量和資源。
libcurl支持3種不同的接口調(diào)用方式,分別是"easy"、"multi"和"share"模式。libcurl-easy是一組同步接口,函數(shù)都是curl_easy_*形式,這種模式調(diào)用curl_easy_perform()函數(shù)進(jìn)行URL數(shù)據(jù)傳輸,直到傳輸完成函數(shù)才返回;libcurl-multi是一組異步接口,函數(shù)都是curl_multi_*形式,調(diào)用curl_multi_perform()函數(shù)進(jìn)行傳輸,但是每次調(diào)用只傳一片數(shù)據(jù),我們可以用select()函數(shù)控制多個(gè)下載任務(wù)進(jìn)行同步下載,來實(shí)現(xiàn)在一個(gè)線程中同時(shí)下載多個(gè)文件;libcurl-share允許在多線程中操作共享數(shù)據(jù)。下面以libcurl-easy為例講一下libcurl的函數(shù)。
1、CURL *curl_easy_init()
此函數(shù)需要最先被調(diào)用,返回CRUL easy句柄;后續(xù)其他函數(shù)調(diào)用都要用到這個(gè)句柄。如果沒有調(diào)用curl_global_init(),該函數(shù)自動(dòng)調(diào)用,但是考慮到線程安全的問題,最好自己調(diào)用curl_global_init()。
2、CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter)
所有參數(shù)和選項(xiàng)設(shè)置都是通過這個(gè)函數(shù)完成的,它告訴libcurl怎樣去進(jìn)行傳輸。參數(shù)handle即為curl_easy_init()返回的句柄,后面根據(jù)option的類型,設(shè)置相應(yīng)的parameter值,該函數(shù)每次調(diào)用只能設(shè)置一個(gè)選項(xiàng)。具體的option講解在這兩篇博文中有較全面的介紹:
http://blog.163.com/wangsen_315/blog/static/9461414200882384555217/
http://blog.sina.com.cn/s/blog_4f9fc6e10100einf.html
這里只總結(jié)一下與下載有關(guān)的常用選項(xiàng)設(shè)置。
CURLOPT_URL
字符串類型,該選項(xiàng)設(shè)置要處理的URL地址,該選項(xiàng)是進(jìn)行curl_easy_perform之前唯一必須要設(shè)置的選項(xiàng)。
CURLOPT_COOKIE
字符串類型,設(shè)置http頭中的cookie信息。
CURLOPT_COOKIEFILE
字符串類型,同CURLOPT_COOKIE,不過cookie信息從文件中讀取。
CURLOPT_FOLLOWLOCATION
布爾值類型,該參數(shù)設(shè)置為非零值表示follow服務(wù)器返回的重定向信息。
CURLOPT_POSTFIELDS
字符串類型,提交http的post操作字符串?dāng)?shù)據(jù)。
CURLOPT_TIMEOUT
long數(shù)值類型,設(shè)置函數(shù)執(zhí)行的最長(zhǎng)時(shí)間,時(shí)間單位為s。
CURLOPT_CONNECTTIMEOUT
long數(shù)值類型,設(shè)置連接服務(wù)器最長(zhǎng)時(shí)間,時(shí)間單位為s;當(dāng)置為0時(shí)表示無限長(zhǎng)。
CURLOPT_MAX_RECV_SPEED_LARGE
curl_off_t類型數(shù)據(jù),指定下載過程中最大速度,單位bytes/s。
CURLOPT_HEADERFUNCTION
函數(shù)指針類型,該選項(xiàng)設(shè)置一個(gè)處理接收到的header數(shù)據(jù)的回調(diào)函數(shù),函數(shù)原型為:
size_t function( void *ptr, size_t size, size_t nmemb, void *stream);
其中,ptr指向接收到的header頭數(shù)據(jù),數(shù)據(jù)大小為size*nmemb,stream指向調(diào)用CURLOPT_WRITEHEADER選項(xiàng)設(shè)置的參數(shù)。該回調(diào)函數(shù)應(yīng)返回實(shí)際處理的數(shù)據(jù)量大小,或者出錯(cuò)返回-1。
CURLOPT_WRITEFUNCTION
函數(shù)指針類型,該選項(xiàng)設(shè)置一個(gè)處理接收到的下載數(shù)據(jù)的回調(diào)函數(shù),函數(shù)原型為:
size_t function( void *ptr, size_t size, size_t nmemb, void *stream);
其中,ptr指向接收到的數(shù)據(jù),數(shù)據(jù)大小為size*nmemb,stream指向調(diào)用CURLOPT_WRITEDATA選項(xiàng)設(shè)置的參數(shù)。
如果函數(shù)指針置為NULL,則會(huì)調(diào)用默認(rèn)的函數(shù),將數(shù)據(jù)寫入到由CURLOPT_WRITEDATA指定的FILE*中。
CURLOPT_HTTPHEADER
curl_slist結(jié)構(gòu)體類型,該選項(xiàng)自定義請(qǐng)求頭信息。
CURLOPT_NOPROGRESS
布爾值類型,設(shè)置該值為非零值關(guān)閉PHP為CRUL傳輸顯示的進(jìn)度條。
3、void curl_easy_reset(CURL *handle )
重新初始化CURL句柄的選項(xiàng)設(shè)置。
4、CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... )
查詢CRUL會(huì)話的內(nèi)部信息,具體說明請(qǐng)參考curl自帶文檔。
5、void curl_easy_cleanup(CURL * handle )
該函數(shù)與curl_easy_init函數(shù)成對(duì)出現(xiàn),handle即為調(diào)用curl_easy_init返回的句柄。該函數(shù)在CURL會(huì)話結(jié)束退出時(shí)調(diào)用,之后handle無效。
The Basic Processes of Using Curl lib.
curl_easy_init() curl_easy_setopt() curl_easy_perform() curl_easy_cleanup()
Upload File by Http Post
curl_global_init(CURL_GLOBAL_WIN32); CURL*easy_handle = curl_easy_init(); // 使用multi-parts form post curl_easy_setopt(easy_handle, CURLOPT_URL,http://localhost:8080/uploadServlet); curl_httppost*post = NULL; curl_httppost *last =NULL; // 文本數(shù)據(jù) curl_formadd(&post,&last, CURLFORM_COPYNAME, "filePath",CURLFORM_COPYCONTENTS, "tempfile", CURLFORM_END); // 文本文件中的數(shù)據(jù) 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();Or
CURL *curl; CURLcode res; curl = curl_easy_init(); if(curl) {curl_formadd(&post, &last, CURLFORM_COPYNAME, "file",CURLFORM_FILE, "C:\\rect.jpg",CURLFORM_END);curl_formadd(&post, &last, CURLFORM_COPYNAME, "name",CURLFORM_COPYCONTENTS, "rect",CURLFORM_END);curl_easy_setopt(curl, CURLOPT_URL, "http://blah.com/upload.php");curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);res = curl_easy_perform(curl);if(res){return 0;}curl_formfree(post); } else {return 0; }curl_easy_cleanup(curl);Upload File with Callback:
#include <stdio.h> #include <string.h>#include <curl/curl.h> #include <curl/types.h> #include <curl/easy.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #ifdef WIN32 #include <io.h> #else #include <unistd.h> #endif/** This example shows an FTP upload, with a rename of the file just after* a successful upload.** Example based on source code provided by Erick Nuwendam. Thanks!*/#define LOCAL_FILE "feed.txt" #define RENAME_FILE_TO "feed.zip"/* NOTE: if you want this example to work on Windows with libcurl as aDLL, you MUST also provide a read callback with CURLOPT_READFUNCTION.Failing to do so will give you a crash since a DLL may not use thevariable's memory when passed in to it from an app like this. */ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream) {/* in real-world cases, this would probably get this data differentlyas this fread() stuff is exactly what the library already would doby default internally */size_t retcode = fread(ptr, size, nmemb, stream);printf("*** We read %d bytes from file\n", retcode);return retcode; }int main(void) {CURL *curl;CURLcode res;FILE *hd_src;struct stat file_info;curl_off_t fsize;char *REMOTE_URL = "http://iss.netii.net/projects/message/";struct curl_slist *headerlist=NULL;static const char buf_2 [] = "RNTO " RENAME_FILE_TO;/* get the file size of the local file */if(stat(LOCAL_FILE, &file_info)) {printf("Couldnt open '%s': %s\n", LOCAL_FILE, strerror(errno));return 1;}fsize = (curl_off_t)file_info.st_size;printf("Local file size: %" CURL_FORMAT_CURL_OFF_T " bytes.\n", fsize);/* get a FILE * of the same file */hd_src = fopen(LOCAL_FILE, "rb");/* In windows, this will init the winsock stuff */curl_global_init(CURL_GLOBAL_ALL);/* get a curl handle */curl = curl_easy_init();if(curl) {/* build a list of commands to pass to libcurl */headerlist = curl_slist_append(headerlist, buf_2);/* we want to use our own read function */curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);/* enable uploading */curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);/* specify target */curl_easy_setopt(curl,CURLOPT_URL, REMOTE_URL);/* pass in that last of FTP commands to run after the transfer */curl_easy_setopt(curl, CURLOPT_POSTQUOTE, headerlist);/* now specify which file to upload */curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);/* Set the size of the file to upload (optional). If you give a *_LARGEoption you MUST make sure that the type of the passed-in argument is acurl_off_t. If you use CURLOPT_INFILESIZE (without _LARGE) you mustmake sure that to pass in a type 'long' argument. */curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,(curl_off_t)fsize);/* Now run off and do what you've been told! */res = curl_easy_perform(curl);/* clean up the FTP commands list */curl_slist_free_all (headerlist);/* always cleanup */curl_easy_cleanup(curl);}fclose(hd_src); /* close the local file */getchar();curl_global_cleanup();return 0; }Download File from Http
#define CURL_STATICLIB #include <stdio.h> #include <curl/curl.h> #include <curl/types.h> #include <curl/easy.h> #include <string>size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {size_t written;written = fwrite(ptr, size, nmemb, stream);return written; }int main(void) {CURL *curl;FILE *fp;CURLcode res;char *url = "http://localhost/aaa.txt";char outfilename[FILENAME_MAX] = "C:\\bbb.txt";curl = curl_easy_init();if (curl) {fp = fopen(outfilename,"wb");curl_easy_setopt(curl, CURLOPT_URL, url);curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);res = curl_easy_perform(curl);curl_easy_cleanup(curl);fclose(fp);}return 0; }
How to Using Curl Command Line:
其中options是下載需要的參數(shù),大約有80多個(gè),curl的各個(gè)功能完全是依靠這些參數(shù)完成的。具體參數(shù)的使用,用戶可以參考curl的man幫助。
-a/--append 上傳文件時(shí),附加到目標(biāo)文件-A/--user-agent <string>? 設(shè)置用戶代理發(fā)送給服務(wù)器- anyauth?? 可以使用“任何”身份驗(yàn)證方法-b/--cookie <name=string/file> cookie字符串或文件讀取位置- basic 使用HTTP基本驗(yàn)證-B/--use-ascii 使用ASCII /文本傳輸-c/--cookie-jar <file> 操作結(jié)束后把cookie寫入到這個(gè)文件中-C/--continue-at <offset>? 斷點(diǎn)續(xù)轉(zhuǎn)-d/--data <data>?? HTTP POST方式傳送數(shù)據(jù)--data-ascii <data>? 以ascii的方式post數(shù)據(jù)--data-binary <data> 以二進(jìn)制的方式post數(shù)據(jù)--negotiate???? 使用HTTP身份驗(yàn)證--digest??????? 使用數(shù)字身份驗(yàn)證--disable-eprt? 禁止使用EPRT或LPRT--disable-epsv? 禁止使用EPSV-D/--dump-header <file> 把header信息寫入到該文件中--egd-file <file> 為隨機(jī)數(shù)據(jù)(SSL)設(shè)置EGD socket路徑--tcp-nodelay?? 使用TCP_NODELAY選項(xiàng)-e/--referer 來源網(wǎng)址-E/--cert <cert[:passwd]> 客戶端證書文件和密碼 (SSL)--cert-type <type> 證書文件類型 (DER/PEM/ENG) (SSL)--key <key>???? 私鑰文件名 (SSL)--key-type <type> 私鑰文件類型 (DER/PEM/ENG) (SSL)--pass? <pass>? 私鑰密碼 (SSL)--engine <eng>? 加密引擎使用 (SSL). "--engine list" for list--cacert <file> CA證書 (SSL)--capath <directory> CA目錄 (made using c_rehash) to verify peer against (SSL)--ciphers <list>? SSL密碼--compressed??? 要求返回是壓縮的形勢(shì) (using deflate or gzip)--connect-timeout <seconds> 設(shè)置最大請(qǐng)求時(shí)間--create-dirs?? 建立本地目錄的目錄層次結(jié)構(gòu)--crlf????????? 上傳是把LF轉(zhuǎn)變成CRLF-f/--fail????????? 連接失敗時(shí)不顯示http錯(cuò)誤--ftp-create-dirs 如果遠(yuǎn)程目錄不存在,創(chuàng)建遠(yuǎn)程目錄--ftp-method [multicwd/nocwd/singlecwd] 控制CWD的使用--ftp-pasv????? 使用 PASV/EPSV 代替端口--ftp-skip-pasv-ip 使用PASV的時(shí)候,忽略該IP地址--ftp-ssl?????? 嘗試用 SSL/TLS 來進(jìn)行ftp數(shù)據(jù)傳輸--ftp-ssl-reqd? 要求用 SSL/TLS 來進(jìn)行ftp數(shù)據(jù)傳輸-F/--form <name=content> 模擬http表單提交數(shù)據(jù)-form-string <name=string> 模擬http表單提交數(shù)據(jù)-g/--globoff 禁用網(wǎng)址序列和范圍使用{}和[]-G/--get 以get的方式來發(fā)送數(shù)據(jù)-h/--help 幫助-H/--header <line>自定義頭信息傳遞給服務(wù)器--ignore-content-length? 忽略的HTTP頭信息的長(zhǎng)度-i/--include 輸出時(shí)包括protocol頭信息-I/--head? 只顯示文檔信息從文件中讀取-j/--junk-session-cookies忽略會(huì)話Cookie- 界面<interface>指定網(wǎng)絡(luò)接口/地址使用- krb4 <級(jí)別>啟用與指定的安全級(jí)別krb4-j/--junk-session-cookies 讀取文件進(jìn)忽略session cookie--interface <interface> 使用指定網(wǎng)絡(luò)接口/地址--krb4 <level>? 使用指定安全級(jí)別的krb4-k/--insecure 允許不使用證書到SSL站點(diǎn)-K/--config? 指定的配置文件讀取-l/--list-only 列出ftp目錄下的文件名稱--limit-rate <rate> 設(shè)置傳輸速度--local-port<NUM> 強(qiáng)制使用本地端口號(hào)-m/--max-time <seconds> 設(shè)置最大傳輸時(shí)間--max-redirs <num> 設(shè)置最大讀取的目錄數(shù)--max-filesize <bytes> 設(shè)置最大下載的文件總量-M/--manual? 顯示全手動(dòng)-n/--netrc 從netrc文件中讀取用戶名和密碼--netrc-optional 使用 .netrc 或者 URL來覆蓋-n--ntlm????????? 使用 HTTP NTLM 身份驗(yàn)證-N/--no-buffer 禁用緩沖輸出-o/--output 把輸出寫到該文件中-O/--remote-name 把輸出寫到該文件中,保留遠(yuǎn)程文件的文件名-p/--proxytunnel?? 使用HTTP代理--proxy-anyauth 選擇任一代理身份驗(yàn)證方法--proxy-basic?? 在代理上使用基本身份驗(yàn)證--proxy-digest? 在代理上使用數(shù)字身份驗(yàn)證--proxy-ntlm??? 在代理上使用ntlm身份驗(yàn)證-P/--ftp-port <address> 使用端口地址,而不是使用PASV-Q/--quote <cmd>文件傳輸前,發(fā)送命令到服務(wù)器-r/--range <range>檢索來自HTTP/1.1或FTP服務(wù)器字節(jié)范圍--range-file 讀取(SSL)的隨機(jī)文件-R/--remote-time?? 在本地生成文件時(shí),保留遠(yuǎn)程文件時(shí)間--retry <num>?? 傳輸出現(xiàn)問題時(shí),重試的次數(shù)--retry-delay <seconds>? 傳輸出現(xiàn)問題時(shí),設(shè)置重試間隔時(shí)間--retry-max-time <seconds> 傳輸出現(xiàn)問題時(shí),設(shè)置最大重試時(shí)間-s/--silent靜音模式。不輸出任何東西-S/--show-error?? 顯示錯(cuò)誤--socks4 <host[:port]> 用socks4代理給定主機(jī)和端口--socks5 <host[:port]> 用socks5代理給定主機(jī)和端口--stderr <file>-t/--telnet-option <OPT=val> Telnet選項(xiàng)設(shè)置--trace <file>? 對(duì)指定文件進(jìn)行debug--trace-ascii <file> Like --跟蹤但沒有hex輸出--trace-time??? 跟蹤/詳細(xì)輸出時(shí),添加時(shí)間戳-T/--upload-file <file> 上傳文件--url <URL>???? Spet URL to work with-u/--user <user[:password]>設(shè)置服務(wù)器的用戶和密碼-U/--proxy-user <user[:password]>設(shè)置代理用戶名和密碼-v/--verbose-V/--version 顯示版本信息-w/--write-out [format]什么輸出完成后-x/--proxy <host[:port]>在給定的端口上使用HTTP代理-X/--request <command>指定什么命令-y/--speed-time 放棄限速所要的時(shí)間。默認(rèn)為30-Y/--speed-limit 停止傳輸速度的限制,速度時(shí)間'秒-z/--time-cond? 傳送時(shí)間設(shè)置-0/--http1.0? 使用HTTP 1.0-1/--tlsv1? 使用TLSv1(SSL)-2/--sslv2 使用SSLv2的(SSL)-3/--sslv3???????? 使用的SSLv3(SSL)--3p-quote????? like -Q for the source URL for 3rd party transfer--3p-url??????? 使用url,進(jìn)行第三方傳送--3p-user?????? 使用用戶名和密碼,進(jìn)行第三方傳送-4/--ipv4?? 使用IP4-6/--ipv6?? 使用IP6-#/--progress-bar 用進(jìn)度條顯示當(dāng)前的傳送狀態(tài)Summary:
curl非常博大,要想用好這個(gè)工具,除了詳細(xì)學(xué)習(xí)參數(shù)之外,還需要深刻理解http的各種協(xié)議與URL的各個(gè)語法。推薦讀物:
RFC 2616 HTTP協(xié)議語法的定義。
RFC 2396 URL語法的定義。
RFC 2109 Cookie是怎樣工作的。
RFC 1867 HTTP如何POST,以及POST的格式。
轉(zhuǎn)載于:https://www.cnblogs.com/yefengmeander/archive/2012/12/26/2887541.html
總結(jié)
以上是生活随笔為你收集整理的Using libcurl in VC++的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于ArcMap中的地图文档单位
- 下一篇: 修改centos7容器的时间和宿主机时间