Using libcurl in VC++
curl是瑞典curl組織開發的,Official Website:
Introduction
curl是一個基于命令行的應用工具,提供利用URL標準進行文件傳輸的功能。
目前已經支持非常多的流行的互聯網協議,如:FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS and FILE等。curl支持SSL認證,HTTP POST/PUT,FTP上傳,HTTP上傳、代理、cookies、用戶+密碼認證、文件續傳、代理管道等一系列強大功能。
curl是用C語言寫的,但是綁定了很多開發語言。大體上可以把curl分成命令行工具和libcurl庫兩個部分,命令行工具可以直接輸入指令完成相應功能,libcurl則是一個客戶端URL傳輸庫,是線程安全且兼容IPv6,可以非常方便地用來做相關開發。
How to Using Curl Lib:
Compile curl without openssl and zlib.
?Step1:下載CURL 最近的幾個版本,我是curl-7.21.5。然后解壓到curl-7.21.5文件夾。
Step2:打開curl-7.21.5文件夾,找到vc6curl.dsw。就是VC6工程的文件。
Step3:用2008打開,選擇 生成(B)-》生成解決方案(F7) ,不要點三角形那個啟動調試
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一起放到你新建的工程目錄你。比如你新建了個名為:DDDDDD的工程,那么久把他們放到\Visual Studio 2008\Projects\DDDDDD\DDDDDD就是有很多.h 和。CPP的地方
Step6:在你工程MAIN函數前面 include"curl/curl.h" 不行的話就用include<curl/curl.h>
Step7:VS2008編代碼的左邊,在工程DDDDDD就是頭文件上方右擊屬性-》配置屬性-》鏈接器-》命令行有個附加選項那打入libcurld_imp.lib就OK了
? 如果運行提示缺少libsasl.dll,就下個SVN,在安裝目錄下的bin目錄下找到libsasl.dll,復制到工程目錄下即可
基于libcurl庫的開發(Windows平臺,MSVC2010開發環境)。
libcurl是一個簡單易用的基于URL傳輸的客戶端開發庫,支持多種平臺以及三十多種開發語言綁定。libcurl是線程安全的,兼容IPv6,功能強大且運行效率高。
在10環境中做libcurl開發,需要將靜態庫文件加到編譯鏈接環境中,并且要dll動態運行庫支持。
libcurl提供了一組C語言API函數直接調用。首先需要提到的兩個函數就是curl_global_init()和curl_global_cleanup()。libcurl要用到一系列的全局常量,curl_global_init()函數就是初始化這些變量,并分配一些全局資源;curl_global_cleanup()則負責釋放這些資源。因此一般情況下,在調用libcurl函數之前,先用curl_global_init(CURL_GLOBAL_ALL)做初始化,在調用完畢后,用curl_global_cleanup()
退出。需要注意的是,這些全局變量和資源并不是線程安全的,因此,在多線程應用的環境中,最好不要多次調用curl_global_init()和curl_global_cleanup(),調用其他函數并不會改變這些全局變量和資源。
libcurl支持3種不同的接口調用方式,分別是"easy"、"multi"和"share"模式。libcurl-easy是一組同步接口,函數都是curl_easy_*形式,這種模式調用curl_easy_perform()函數進行URL數據傳輸,直到傳輸完成函數才返回;libcurl-multi是一組異步接口,函數都是curl_multi_*形式,調用curl_multi_perform()函數進行傳輸,但是每次調用只傳一片數據,我們可以用select()函數控制多個下載任務進行同步下載,來實現在一個線程中同時下載多個文件;libcurl-share允許在多線程中操作共享數據。下面以libcurl-easy為例講一下libcurl的函數。
1、CURL *curl_easy_init()
此函數需要最先被調用,返回CRUL easy句柄;后續其他函數調用都要用到這個句柄。如果沒有調用curl_global_init(),該函數自動調用,但是考慮到線程安全的問題,最好自己調用curl_global_init()。
2、CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter)
所有參數和選項設置都是通過這個函數完成的,它告訴libcurl怎樣去進行傳輸。參數handle即為curl_easy_init()返回的句柄,后面根據option的類型,設置相應的parameter值,該函數每次調用只能設置一個選項。具體的option講解在這兩篇博文中有較全面的介紹:
http://blog.163.com/wangsen_315/blog/static/9461414200882384555217/
http://blog.sina.com.cn/s/blog_4f9fc6e10100einf.html
這里只總結一下與下載有關的常用選項設置。
CURLOPT_URL
字符串類型,該選項設置要處理的URL地址,該選項是進行curl_easy_perform之前唯一必須要設置的選項。
CURLOPT_COOKIE
字符串類型,設置http頭中的cookie信息。
CURLOPT_COOKIEFILE
字符串類型,同CURLOPT_COOKIE,不過cookie信息從文件中讀取。
CURLOPT_FOLLOWLOCATION
布爾值類型,該參數設置為非零值表示follow服務器返回的重定向信息。
CURLOPT_POSTFIELDS
字符串類型,提交http的post操作字符串數據。
CURLOPT_TIMEOUT
long數值類型,設置函數執行的最長時間,時間單位為s。
CURLOPT_CONNECTTIMEOUT
long數值類型,設置連接服務器最長時間,時間單位為s;當置為0時表示無限長。
CURLOPT_MAX_RECV_SPEED_LARGE
curl_off_t類型數據,指定下載過程中最大速度,單位bytes/s。
CURLOPT_HEADERFUNCTION
函數指針類型,該選項設置一個處理接收到的header數據的回調函數,函數原型為:
size_t function( void *ptr, size_t size, size_t nmemb, void *stream);
其中,ptr指向接收到的header頭數據,數據大小為size*nmemb,stream指向調用CURLOPT_WRITEHEADER選項設置的參數。該回調函數應返回實際處理的數據量大小,或者出錯返回-1。
CURLOPT_WRITEFUNCTION
函數指針類型,該選項設置一個處理接收到的下載數據的回調函數,函數原型為:
size_t function( void *ptr, size_t size, size_t nmemb, void *stream);
其中,ptr指向接收到的數據,數據大小為size*nmemb,stream指向調用CURLOPT_WRITEDATA選項設置的參數。
如果函數指針置為NULL,則會調用默認的函數,將數據寫入到由CURLOPT_WRITEDATA指定的FILE*中。
CURLOPT_HTTPHEADER
curl_slist結構體類型,該選項自定義請求頭信息。
CURLOPT_NOPROGRESS
布爾值類型,設置該值為非零值關閉PHP為CRUL傳輸顯示的進度條。
3、void curl_easy_reset(CURL *handle )
重新初始化CURL句柄的選項設置。
4、CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... )
查詢CRUL會話的內部信息,具體說明請參考curl自帶文檔。
5、void curl_easy_cleanup(CURL * handle )
該函數與curl_easy_init函數成對出現,handle即為調用curl_easy_init返回的句柄。該函數在CURL會話結束退出時調用,之后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; // 文本數據 curl_formadd(&post,&last, CURLFORM_COPYNAME, "filePath",CURLFORM_COPYCONTENTS, "tempfile", CURLFORM_END); // 文本文件中的數據 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是下載需要的參數,大約有80多個,curl的各個功能完全是依靠這些參數完成的。具體參數的使用,用戶可以參考curl的man幫助。
-a/--append 上傳文件時,附加到目標文件-A/--user-agent <string>? 設置用戶代理發送給服務器- anyauth?? 可以使用“任何”身份驗證方法-b/--cookie <name=string/file> cookie字符串或文件讀取位置- basic 使用HTTP基本驗證-B/--use-ascii 使用ASCII /文本傳輸-c/--cookie-jar <file> 操作結束后把cookie寫入到這個文件中-C/--continue-at <offset>? 斷點續轉-d/--data <data>?? HTTP POST方式傳送數據--data-ascii <data>? 以ascii的方式post數據--data-binary <data> 以二進制的方式post數據--negotiate???? 使用HTTP身份驗證--digest??????? 使用數字身份驗證--disable-eprt? 禁止使用EPRT或LPRT--disable-epsv? 禁止使用EPSV-D/--dump-header <file> 把header信息寫入到該文件中--egd-file <file> 為隨機數據(SSL)設置EGD socket路徑--tcp-nodelay?? 使用TCP_NODELAY選項-e/--referer 來源網址-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??? 要求返回是壓縮的形勢 (using deflate or gzip)--connect-timeout <seconds> 設置最大請求時間--create-dirs?? 建立本地目錄的目錄層次結構--crlf????????? 上傳是把LF轉變成CRLF-f/--fail????????? 連接失敗時不顯示http錯誤--ftp-create-dirs 如果遠程目錄不存在,創建遠程目錄--ftp-method [multicwd/nocwd/singlecwd] 控制CWD的使用--ftp-pasv????? 使用 PASV/EPSV 代替端口--ftp-skip-pasv-ip 使用PASV的時候,忽略該IP地址--ftp-ssl?????? 嘗試用 SSL/TLS 來進行ftp數據傳輸--ftp-ssl-reqd? 要求用 SSL/TLS 來進行ftp數據傳輸-F/--form <name=content> 模擬http表單提交數據-form-string <name=string> 模擬http表單提交數據-g/--globoff 禁用網址序列和范圍使用{}和[]-G/--get 以get的方式來發送數據-h/--help 幫助-H/--header <line>自定義頭信息傳遞給服務器--ignore-content-length? 忽略的HTTP頭信息的長度-i/--include 輸出時包括protocol頭信息-I/--head? 只顯示文檔信息從文件中讀取-j/--junk-session-cookies忽略會話Cookie- 界面<interface>指定網絡接口/地址使用- krb4 <級別>啟用與指定的安全級別krb4-j/--junk-session-cookies 讀取文件進忽略session cookie--interface <interface> 使用指定網絡接口/地址--krb4 <level>? 使用指定安全級別的krb4-k/--insecure 允許不使用證書到SSL站點-K/--config? 指定的配置文件讀取-l/--list-only 列出ftp目錄下的文件名稱--limit-rate <rate> 設置傳輸速度--local-port<NUM> 強制使用本地端口號-m/--max-time <seconds> 設置最大傳輸時間--max-redirs <num> 設置最大讀取的目錄數--max-filesize <bytes> 設置最大下載的文件總量-M/--manual? 顯示全手動-n/--netrc 從netrc文件中讀取用戶名和密碼--netrc-optional 使用 .netrc 或者 URL來覆蓋-n--ntlm????????? 使用 HTTP NTLM 身份驗證-N/--no-buffer 禁用緩沖輸出-o/--output 把輸出寫到該文件中-O/--remote-name 把輸出寫到該文件中,保留遠程文件的文件名-p/--proxytunnel?? 使用HTTP代理--proxy-anyauth 選擇任一代理身份驗證方法--proxy-basic?? 在代理上使用基本身份驗證--proxy-digest? 在代理上使用數字身份驗證--proxy-ntlm??? 在代理上使用ntlm身份驗證-P/--ftp-port <address> 使用端口地址,而不是使用PASV-Q/--quote <cmd>文件傳輸前,發送命令到服務器-r/--range <range>檢索來自HTTP/1.1或FTP服務器字節范圍--range-file 讀取(SSL)的隨機文件-R/--remote-time?? 在本地生成文件時,保留遠程文件時間--retry <num>?? 傳輸出現問題時,重試的次數--retry-delay <seconds>? 傳輸出現問題時,設置重試間隔時間--retry-max-time <seconds> 傳輸出現問題時,設置最大重試時間-s/--silent靜音模式。不輸出任何東西-S/--show-error?? 顯示錯誤--socks4 <host[:port]> 用socks4代理給定主機和端口--socks5 <host[:port]> 用socks5代理給定主機和端口--stderr <file>-t/--telnet-option <OPT=val> Telnet選項設置--trace <file>? 對指定文件進行debug--trace-ascii <file> Like --跟蹤但沒有hex輸出--trace-time??? 跟蹤/詳細輸出時,添加時間戳-T/--upload-file <file> 上傳文件--url <URL>???? Spet URL to work with-u/--user <user[:password]>設置服務器的用戶和密碼-U/--proxy-user <user[:password]>設置代理用戶名和密碼-v/--verbose-V/--version 顯示版本信息-w/--write-out [format]什么輸出完成后-x/--proxy <host[:port]>在給定的端口上使用HTTP代理-X/--request <command>指定什么命令-y/--speed-time 放棄限速所要的時間。默認為30-Y/--speed-limit 停止傳輸速度的限制,速度時間'秒-z/--time-cond? 傳送時間設置-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,進行第三方傳送--3p-user?????? 使用用戶名和密碼,進行第三方傳送-4/--ipv4?? 使用IP4-6/--ipv6?? 使用IP6-#/--progress-bar 用進度條顯示當前的傳送狀態Summary:
curl非常博大,要想用好這個工具,除了詳細學習參數之外,還需要深刻理解http的各種協議與URL的各個語法。推薦讀物:
RFC 2616 HTTP協議語法的定義。
RFC 2396 URL語法的定義。
RFC 2109 Cookie是怎樣工作的。
RFC 1867 HTTP如何POST,以及POST的格式。
轉載于:https://www.cnblogs.com/yefengmeander/archive/2012/12/26/2887541.html
總結
以上是生活随笔為你收集整理的Using libcurl in VC++的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于ArcMap中的地图文档单位
- 下一篇: 修改centos7容器的时间和宿主机时间