libCURL是一個免費的、開源的強大客戶端url傳輸庫。支持的平台、協議甚廣。平台上有Windows、Linux、FreeBSD;協議上有FTP、HTTP(S)、Telnet、DICT、File等。它是線程安全的,而且支持ipv6。同時,它還是線程安全的。
本文所講述的內容,要基於Libcurl的基礎、具體的了解。官方具體描述地址在:http://curl.haxx.se/libcurl/c/上面。需要多看例子,才能靈活運用。
通常libCURL的數據下載都是通過回調函數下載到buffer中的。其大小一般固定,所以有時候用了不到1/2,有時候卻會overflow。這裡給出一個簡單易用的方法節約內存,並解決溢出。主要思想是使用STL中的list的char*模板,每次回調時都copy到一個分配了一定內存的指針(要注意的是,libCURL給出的是流數據,所以不一定以0結尾,所以有時候用簡單的strcpy時,會出現錯誤,筆者就在這被坑了很多次),其大小為size*nmemb,然後將給出的數據逐個copy後,push_back到鏈表即可。
使用這些數據時,有可能需要隨機存取,但是list不具備這個特征,所以可以先統計出所有數據的總大小,開一個大buffer,存入即可。當然,在此之後,要把所有的list及char指針釋放,否則內存還是雙倍。
源代碼給出如下:
#include <iostream> #include <list> #include <curl/curl.h> using namespace std; size_t callback_get_head(void *ptr,size_t size,size_t nmemb,void *userp); list<char*> toview; char startht[256]={0}; int main(void){ cout<<"Enter HTTP adress:"; cin>>startht; CURL* dcurl=curl_easy_init(); curl_easy_setopt(dcurl,CURLOPT_URL,startht); curl_easy_setopt(dcurl,CURLOPT_WRITEFUNCTION,callback_get_head); curl_easy_perform(dcurl); for (list<char*>::iterator it=toview.begin();it!=toview.end();++it) cout<<*it; for (list<char*>::iterator it=toview.begin();it!=toview.end();++it) delete[] *it; curl_easy_cleanup(dcurl); return 0; } size_t callback_get_head(void *ptr,size_t size,size_t nmemb,void *userp){ char* temp=new char[size*nmemb+1]; char* ptrtmp=(char*) ptr; for (size_t i=0;i<size*nmemb;++i) temp[i]=ptrtmp[i]; temp[size*nmemb+1]=0; toview.push_back(temp); return size*nmemb; }