Curl的移植編譯以及注意事項
最近需要用curl來發送http請求,遇到了不少問題,查了不少資料,都是零零散散的,現在總結下。
1、移植編譯
1 ./configure --prefix=$(PWD)/build --host=arm-XXX-linux;make ;make install
這步基本都沒有問題,生成的動態連結庫libcurl.a,可以直接給應用程式去使用。
2、API使用
1)全域性初始化 curl_global_init(CURL_GLOBAL_ALL);
2)通過curl_easy_init得到一個CURL指標m_pCurl
3)通過curl_formadd封裝引數
通過curl_easy_setopt設定各種選項
通過curl_easy_perform執行curl的各種操作
4)curl_easy_getinfo 獲得http返回的狀態碼
5)curl_easy_cleanup釋放CURL指標
6)curl_global_cleanup釋放全域性物件
3、http的響應內容獲取
先通過 curl_easy_setopt設定CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA選項
size_t ReviceData(char *buffer, size_t size, size_t nmemb, std::stringstream & stream) { size_t total = size * nmemb; std::string str = ""; if (total) { str.append(buffer, total); } stream << str.c_str(); return total; } std::stringstream out; curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, ReviceData); curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, &out);
當有響應回來的時候,會觸發ReviceData函式,在這個回撥函式,會把響應的內容,賦值給out變數,這樣響應就取得了。
4、遇到的一些問題
curl_easy_setopt(m_pCurl, CURLOPT_CONNECTTIMEOUT, 4L);
curl_easy_setopt(m_pCurl, CURLOPT_TIMEOUT, 25L);
設定了超時時間後(一個是等待連線的時間,一個是等待接收響應的時間)一旦域名解析失敗,程式會莫名的掛掉,而且每次掛掉的地方都不一樣。當時也是通過一點一點註釋程式碼,才定位到這兩行程式碼。
coredump的原因是因為curl的DNS解析超時控制是使用SIGALARM實現的。
這樣導致發現SIGALARM會出現多執行緒修改同一個全域性變數,由此產生了COREDUMP。
問題發生的前提是設定了CURLOPT_TIMEOUT或CURLOPT_CONNECTTIMEOUT,並且值不為0。
解決辦法:
1) 設定CURLOPT_NOSIGNAL的值為1
curl_easy_setopt(m_pCurl, CURLOPT_NOSIGNAL, 1);
設定之後,發現的確不會coredump了,但是設定的超時時間沒有用了,需要等很久,才能出結果。
2) 使用c-ares(configure時指定引數--enable-ares)
使用這個方法比較好,不會coredump,而且超時時間設定後生效。
下面介紹下這個方法:
a、下載cares的原始碼,進行編譯移植
https://c-ares.haxx.se/
編譯方法和curl的編譯方法類似,都是通過configure ,最終生成libcares.a
b、修改curl原始碼裡的configure檔案
找到下面的程式碼,新增embedded_ares="yes",箭頭所指的地方,不然check
的時候,會報c-ares library defective or too old
c、重新編譯curl
./configure --enable-ares=$(PWD)/depends --prefix=$(PWD)/build --host=arm-XXX-linux;make ;make install
這裡指定了enable-ares使用的libares所在的目錄。depends目錄下需要再建立一個子目錄lib,在子目錄下放入libcares.a即可。
還要把libcares的標頭檔案都拷貝到curl主目錄裡的lib目錄裡,這樣編譯就不會出錯了。
&n