(轉)libcurl庫使用方法,好長,好詳細。

1、ibcurl做爲是一個多協議的便於客戶端使用的URL傳輸庫,基於C語言,提供C語言的API接口,支持DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet and TFTP這些協議,同時支持使用SSL證書的安全文件傳輸:HTTP POST, HTTP PUT, FTP 上傳, 基於HTTP形式的上傳、代理、Cookies、用戶加密碼的認證等多種應用場景。另外,libcurl是一個高移植性的庫,能在絕大多數系統上運行,包括Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HPUX, IRIX, AIX, Tru64, Linux, UnixWare, HURD, Windows, Amiga, OS/2, BeOs, Mac OS X, Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS等。html

2、使用步驟
1. 調用curl_global_init()初始化libcurl
2. 調用curl_easy_init()函數獲得 easy interface型指針
3. 調用curl_easy_setopt()設置傳輸選項
4. 根據curl_easy_setopt()設置的傳輸選項,實現回調函數以完成用戶特定任務
5. 調用curl_easy_perform()函數完成傳輸任務
6. 調用curl_easy_cleanup()釋放內存node

7.調用curl_global_cleanup()析構libcurl
在整過過程當中設置curl_easy_setopt()參數是最關鍵的,幾乎全部的libcurl程序都要使用它。ios

在基於LibCurl的程序裏,主要採用callback function (回調函數)的形式完成傳輸任務,用戶在啓動傳輸前設置好各種參數和回調函數,當知足條件時libcurl將調用用戶的回調函數實現特定功能。git

3、函數說明json

1.CURLcode curl_global_init(long flags);
描述:
這個函數只能用一次。(其實在調用curl_global_cleanup 函數後仍然可再用)
若是這個函數在curl_easy_init函數調用時還沒調用,它講由libcurl庫自動調用,因此多線程下最好主動調用該函數以防止在線程中curl_easy_init時屢次調用。api

注意:雖然libcurl是線程安全的,但curl_global_init是不能保證線程安全的,因此不要在每一個線程中都調用curl_global_init,應該將該函數的調用放在主線程中。
參數:flags
CURL_GLOBAL_ALL                      //初始化全部的可能的調用。
CURL_GLOBAL_SSL                      //初始化支持 安全套接字層。
CURL_GLOBAL_WIN32            //初始化win32套接字庫。
CURL_GLOBAL_NOTHING         //沒有額外的初始化。安全


2 void curl_global_cleanup(void);
描述:在結束libcurl使用的時候,用來對curl_global_init作的工做清理。相似於close的函數。服務器

注意:雖然libcurl是線程安全的,但curl_global_cleanup是不能保證線程安全的,因此不要在每一個線程中都調用curl_global_init,應該將該函數的調用放在主線程中。cookie


3 char *curl_version( );
描述: 打印當前libcurl庫的版本。網絡


4 CURL *curl_easy_init( );
描述:
curl_easy_init用來初始化一個CURL的指針(有些像返回FILE類型的指針同樣). 相應的在調用結束時要用curl_easy_cleanup函數清理.
通常curl_easy_init意味着一個會話的開始. 它會返回一個easy_handle(CURL*對象), 通常都用在easy系列的函數中.


5 void curl_easy_cleanup(CURL *handle);
描述:
這個調用用來結束一個會話.與curl_easy_init配合着用. 
參數:
CURL類型的指針.


6 CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
描述: 這個函數最重要了.幾乎全部的curl 程序都要頻繁的使用它.它告訴curl庫.程序將有如何的行爲. 好比要查看一個網頁的html代碼等.(這個函數有些像ioctl函數)參數:
1 CURL類型的指針
2 各類CURLoption類型的選項.(都在curl.h庫裏有定義,man 也能夠查看到)
3 parameter 這個參數 既能夠是個函數的指針,也能夠是某個對象的指針,也能夠是個long型的變量.它用什麼這取決於第二個參數.
CURLoption 這個參數的取值不少.具體的能夠查看man手冊.


7 CURLcode curl_easy_perform(CURL *handle);

描述:這個函數在初始化CURL類型的指針 以及curl_easy_setopt完成後調用. 就像字面的意思所說perform就像是個舞臺.讓咱們設置的
option 運做起來.參數:
CURL類型的指針.

8 void curl_global_cleanup(void);

釋放libcurl

 

4、curl_easy_setopt函數部分選項介紹
本節主要介紹curl_easy_setopt中跟http相關的參數。該函數是curl中很是重要的函數,curl全部設置都是在該函數中完成的,該函數的設置選項衆多,注意本節的闡述的只是部分常見選項。

     CURLOPT_URL 
設置訪問URL

       CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA
回調函數原型爲:size_t function( void *ptr, size_t size, size_t nmemb, void *stream); 函數將在libcurl接收到數據後被調用,所以函數多作數據保存的功能,如處理下載文件。CURLOPT_WRITEDATA 用於代表CURLOPT_WRITEFUNCTION函數中的stream指針的來源。
若是你沒有經過CURLOPT_WRITEFUNCTION屬性給easy handle設置回調函數,libcurl會提供一個默認的回調函數,它只是簡單的將接收到的數據打印到標準輸出。你也能夠經過 CURLOPT_WRITEDATA屬性給默認回調函數傳遞一個已經打開的文件指針,用於將數據輸出到文件裏。


      CURLOPT_HEADERFUNCTION,CURLOPT_HEADERDATA
回調函數原型爲 size_t function( void *ptr, size_t size,size_t nmemb, void *stream); libcurl一旦接收到http 頭部數據後將調用該函數。CURLOPT_WRITEDATA 傳遞指針給libcurl,該指針代表CURLOPT_HEADERFUNCTION 函數的stream指針的來源。

       CURLOPT_READFUNCTION CURLOPT_READDATA
libCurl須要讀取數據傳遞給遠程主機時將調用CURLOPT_READFUNCTION指定的函數,函數原型是:size_t function(void *ptr, size_t size, size_t nmemb,void *stream). CURLOPT_READDATA 代表CURLOPT_READFUNCTION函數原型中的stream指針來源。

       CURLOPT_NOPROGRESS,CURLOPT_PROGRESSFUNCTION,CURLOPT_PROGRESSDATA
跟數據傳輸進度相關的參數。CURLOPT_PROGRESSFUNCTION 指定的函數正常狀況下每秒被libcurl調用一次,爲了使CURLOPT_PROGRESSFUNCTION被調用,CURLOPT_NOPROGRESS必須被設置爲false,CURLOPT_PROGRESSDATA指定的參數將做爲CURLOPT_PROGRESSFUNCTION指定函數的第一個參數

       CURLOPT_TIMEOUT,CURLOPT_CONNECTIONTIMEOUT:
CURLOPT_TIMEOUT 因爲設置傳輸時間,CURLOPT_CONNECTIONTIMEOUT 設置鏈接等待時間

      CURLOPT_FOLLOWLOCATION
設置重定位URL

       CURLOPT_RANGE: CURLOPT_RESUME_FROM:
斷點續傳相關設置。CURLOPT_RANGE 指定char *參數傳遞給libcurl,用於指明http域的RANGE頭域,例如:
表示頭500個字節:bytes=0-499
表示第二個500字節:bytes=500-999
表示最後500個字節:bytes=-500
表示500字節之後的範圍:bytes=500-
第一個和最後一個字節:bytes=0-0,-1
同時指定幾個範圍:bytes=500-600,601-999
CURLOPT_RESUME_FROM 傳遞一個long參數給libcurl,指定你但願開始傳遞的 偏移量。
5、libcurl使用的HTTP消息頭

當使用libcurl發送http請求時,它會自動添加一些http頭。咱們能夠經過CURLOPT_HTTPHEADER屬性手動替換、添加或刪除相應 的HTTP消息頭。
    Host
    http1.1(大部分http1.0)版本都要求客戶端請求提供這個信息頭。
    Pragma
    "no-cache"。表示不要緩衝數據。
    Accept
    "*/*"。表示容許接收任何類型的數據。
    Expect
    以POST的方式向HTTP服務器提交請求時,libcurl會設置該消息頭爲"100-continue",它要求服務器在正式處理該請求以前,返回一 個"OK"消息。若是POST的數據很小,libcurl可能不會設置該消息頭。
自定義選項
    當前愈來愈多的協議都構建在HTTP協議之上(如:soap),這主要歸功於HTTP的可靠性,以及被普遍使用的代理支持(能夠穿透大部分防火牆)。 這些協議的使用方式與傳統HTTP可能有很大的不一樣。對此,libcurl做了很好的支持。
    自定義請求方式(CustomRequest)
    HTTP支持GET, HEAD或者POST提交請求。能夠設置CURLOPT_CUSTOMREQUEST來設置自定義的請求方式,libcurl默認以GET方式提交請求:
    curl_easy_setopt(easy_handle, CURLOPT_CUSTOMREQUEST, "MYOWNREQUEST"); 

struct curl_slist *headers=NULL; /* init to NULL is important */ headers = curl_slist_append(headers, "Hey-server-hey: how are you?"); headers = curl_slist_append(headers, "X-silly-content: yes"); /* pass our list of custom made headers */ curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers); curl_easy_perform(easyhandle); /* transfer http */ curl_slist_free_all(headers); /* free the header list */

 

6、獲取http應答頭信息

    發出http請求後,服務器會返回應答頭信息和應答數據,若是僅僅是打印應答頭的全部內容,則直接能夠經過curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, 打印函數)的方式來完成,這裏須要獲取的是應答頭中特定的信息,好比應答碼、cookies列表等,則須要經過下面這個函數:
    CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... ); 
    info參數就是咱們須要獲取的內容,下面是一些參數值:
    1.CURLINFO_RESPONSE_CODE
    獲取應答碼
    2.CURLINFO_HEADER_SIZE
    頭大小
    3.CURLINFO_COOKIELIST
    cookies列表

除了獲取應答信息外,這個函數還能獲取curl的一些內部信息,如請求時間、鏈接時間等等。

 

7、多線程問題
    首先一個基本原則就是:絕對不該該在線程之間共享同一個libcurl handle(CURL *對象),無論是easy handle仍是multi handle(本文只介紹easy_handle)。一個線程每次只能使用一個handle。
    libcurl是線程安全的,但有兩點例外:信號(signals)和SSL/TLS handler。 信號用於超時失效名字解析(timing out name resolves)。libcurl依賴其餘的庫來支持SSL/STL,因此用多線程的方式訪問HTTPS或FTPS的URL時,應該知足這些庫對多線程 操做的一些要求。詳細能夠參考:
    OpenSSL: http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION

    GnuTLS: http://www.gnu.org/software/gnutls/manual/html_node/Multi_002dthreaded-applications.html

8、HTTP驗證
    在使用HTTP協議時,客戶端有不少種方式向服務器提供驗證信息。默認的 HTTP驗證方法是"Basic」,它將用戶名與密碼以明文的方式、經Base64編碼後保存在HTTP請求頭中,發往服務器。固然這不太安全。
    當前版本的libcurl支持的驗證方法有:basic, Digest, NTLM, Negotiate, GSS-Negotiate and SPNEGO。能夠經過CURLOPT_HTTPAUTH屬性來設置具體 的驗證方式:
    curl_easy_setopt(easy_handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
    向代理服務器發送驗證信息時,能夠經過CURLOPT_PROXYAUTH設置驗證方式:
    curl_easy_setopt(easy_handle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
    也能夠同時設置多種驗證方式(經過按位與), 使用‘CURLAUTH_ANY‘將容許libcurl能夠選擇任何它所支持的驗證方式。經過CURLOPT_HTTPAUTH或 CURLOPT_PROXYAUTH屬性設置的多種驗證方式,libcurl會在運行時選擇一種它認爲是最好的方式與服務器通訊:
    curl_easy_setopt(easy_handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC); 
    // curl_easy_setopt(easy_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);

 

9、編譯libcurl庫

從網站https://curl.haxx.se/download找到源碼包,官網最新版爲7.56.0,可是這個壓縮包的curl-7.56.0\projects\Windows路徑下VC6-VC14各個版本的VS解決方案。

9.1 若是須要libcur支持https,須要openssl庫支持。

libcurl主要功能就是用不一樣的協議鏈接和溝通不一樣的服務器,若是使用HTTPS,須要OpenSSL

libcurl https://curl.haxx.se/download.html 下載Source Archives便可

ActiveState https://www.activestate.com/activeperl/downloads 下載perl解析器,編譯openssl須要用到。

openssl https://www.openssl.org/source/ 下載openssl-1.0.2k,1.1.0之後的文件和安裝方法都換了。

zlib http://zlib.net/ 下載1.2.7之外的版本,好比1.2.11。

支持https的libcurl庫編譯方法:

1)解壓

爲了方便安裝,在D盤根目錄下新建一個名爲libcurl-ssl的文件夾,將下載的三個壓縮包解壓到該文件夾。
在 curl-7.54.0 -> lib 下新建文件夾openssl用來存放openssl的頭文件。

2) zlib編譯:

zlib-1.2.11\contrib\vstudio\vc14\zlibvc.sln,編譯release版本。

在生成的x86\ZlibDllRelease文件夾中有zlibwapi.dll和zlibwapi.lib文件

3) ActiveState安裝:

打開安裝包,選擇Modify默認安裝或Repair修改安裝路徑均可以

4) openssl編譯:

這是最麻煩、最容易出錯的一環了,由於他沒有項目文件,只能經過命令行來編譯。

在開始菜單中找到vs自帶的 VS2015 x86 本機工具命令提示符

使用cd命令進入到openssl-1.0.2k文件夾中

命令行鍵入 perl Configure VC-WIN32 no-asm

命令行鍵入 ms\do_ms.bat

命令行鍵入 nmake -f ms/ntdll.mak

等待差很少五分鐘,只要不出現「stop」,安全地執行到結束,就算成功。
一旦中間出了差錯,最好是把文件夾也刪了,從新解壓、配置編譯,若是你留有編譯失敗的半成品,它可能會告訴你「沒法解析XXX」。

5) 將 openssl-1.0.2k -> inc32 -> openssl 全部的.h 和 openssl-1.0.2k -> out32dll 的 libeay32.lib、libeay32.dll、ssleay32.lib、ssleay32.dll 一塊兒複製到 curl-7.54.0 -> lib -> openssl 中

libcurl編譯:

編譯平臺選擇 DLL Debug - DLL OpenSSL

curl-7.54.0 ->projects -> Windows -> VC14 -> curl-all.sln,可能會提示升級工程,肯定便可。

將 libcurl 設爲啓動項目,選擇 libcurl -> Resource Files -> libcurl.rc,右鍵「移出」,它記錄着版本信息,只會增大文件,能夠移出掉。

選擇 屬性 -> C/C++ -> 預處理器 -> 預處理器定義,將"BUILDING_LIBCURL"改爲"CURL_STATICLIB"。這樣那些接口函數就不會被聲明爲導出函數了。

選擇 屬性 -> 連接器 -> 常規 -> 附加庫目錄 添加 ..\..\..\..\lib\openssl,指向curl-7.54.0 -> lib -> openssl

選擇 屬性 -> 連接器 -> 輸入 -> 附加依賴項 添加 libeay32.lib;ssleay32.lib;ws2_32.lib;wldap32.lib; 前兩個是爲了OpenSSL,後兩個是CURL必須依賴的。

在編譯成功後 curl-7.54.0 -> build -> Win32 -> VC14 -> DLL Debug - DLL OpenSSL 文件夾中會生成有 libcurld.dll 和 libcurld.lib(注意名字不是libcurl)。

 

9.2不支持https的libcurl庫編譯方法:

使用curl-7.32.0版本中vs工程,vc自動編譯。從網站https://curl.haxx.se/download 中下載curl-7.32.0版本。解壓curl-7.32.0,找到vs工程目錄,好比:curl-7.32.0\vs\vc8\lib\vc8libcurl.vcproj

1) 打開curl-7.32.0\vs\vc8\lib\vc8libcurl.vcproj文件,VS2010會提示升級工程,下一步便可。
VC工程裏有些設置問題致使不能直接編譯,須要稍做修改

2) 打開工程屬性 > C\C++ > 常規 > 附加包含目錄。這裏的包含目錄是"..\include",而這個目錄根本就不存在,它應該指向"curl-7.32.0\include"纔對,因此把這裏改爲"..\..\..\include"。(或者直接完整路徑也能夠)

3) 打開工程屬性 > C\C++ > 預處理器 > 預處理器定義。這裏有個默認宏"BUILDING_LIBCURL",若是要編譯生成靜態庫,則要把它改爲"CURL_STATICLIB"。這樣,那些接口函數就不會被聲明爲導出函數了。

4) 打開工程屬性 > C\C++ > 庫管理器 > 常規 > 附加依賴項。添加ws2_32.lib和wldap32.lib,這是CURL必須依賴的。或者在代碼中使用#pragma comment預編譯指令,手動引入這兩個lib庫。

 

9.3 libcurld.lib/libcurl.lib引用方法

將 curl-7.54.0 -> include 目錄下的curl文件夾,複製過去。

將libcurl編譯的 libcurld.dll 和 libcurld.lib 複製到debug。

將libcurld.dll和以前OpenSSL生成的 libeay32.dll、ssleay32.dll 各複製一份到項目文件夾下,不然會報錯。

選擇 配置屬性 -> C\C++ -> 預處理器 -> 預處理器定義,添加CURL_STATICLIB。

屬性中的 附加包含目錄、附加庫目錄和附加依賴項就在代碼中實現。

10、實例代碼

 1 #define CURL_STATICLIB                //若是是靜態庫方式,須要包含這句
 2  
 3 #include "curl\curl.h"
 4 #include <iostream>
 5 #include <list>
 6 #include <string>
 7  
 8 #ifdef _DEBUG  9 #pragma comment(lib,"libcurld.lib")
 10 #else
 11 #pragma comment(lib,"libcurl.lib")
 12 #endif
 13  
 14 #pragma comment ( lib, "ws2_32.lib" )
 15 #pragma comment ( lib, "winmm.lib" )
 16 #pragma comment ( lib, "wldap32.lib" )
 17 #pragma comment(lib, "Advapi32.lib")
 18  
 19  
 20 std::wstring AsciiToUnicode(const std::string& str)  21 {  22     // 預算-緩衝區中寬字節的長度 
 23     int unicodeLen = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, nullptr, 0);  24     // 給指向緩衝區的指針變量分配內存 
 25     wchar_t *pUnicode = (wchar_t*)malloc(sizeof(wchar_t)*unicodeLen);  26     // 開始向緩衝區轉換字節 
 27     MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, pUnicode, unicodeLen);  28     std::wstring ret_str = pUnicode;  29     free(pUnicode);  30     return ret_str;  31 }  32  
 33 std::string UnicodeToUtf8(const std::wstring& wstr)  34 {  35     // 預算-緩衝區中多字節的長度 
 36     int ansiiLen = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);  37     // 給指向緩衝區的指針變量分配內存 
 38     char *pAssii = (char*)malloc(sizeof(char)*ansiiLen);  39     // 開始向緩衝區轉換字節 
 40     WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, pAssii, ansiiLen, nullptr, nullptr);  41     std::string ret_str = pAssii;  42     free(pAssii);  43     return ret_str;  44 }  45  
 46 //ANSI轉UTF8
 47 std::string AsciiToUtf8(const std::string& str)  48 {  49     return UnicodeToUtf8(AsciiToUnicode(str));  50 }  51  
 52 //UTF8轉ANSI
 53 std::string Utf8toAscii(const std::string strUTF8)  54 {  55     std::string  strAnsi = "";  56     //獲取轉換爲多字節後須要的緩衝區大小,建立多字節緩衝區
 57     UINT nLen = MultiByteToWideChar(CP_UTF8, NULL, strUTF8.c_str(), -1, NULL, NULL);  58     WCHAR *wszBuffer = new WCHAR[nLen + 1];  59     nLen = MultiByteToWideChar(CP_UTF8, NULL, strUTF8.c_str(), -1, wszBuffer, nLen);  60     wszBuffer[nLen] = 0;  61     nLen = WideCharToMultiByte(936, NULL, wszBuffer, -1, NULL, NULL, NULL, NULL);  62     CHAR *szBuffer = new CHAR[nLen + 1];  63     nLen = WideCharToMultiByte(936, NULL, wszBuffer, -1, szBuffer, nLen, NULL, NULL);  64     szBuffer[nLen] = 0;  65     strAnsi = szBuffer;  66     //清理內存
 67  delete[]szBuffer;  68  delete[]wszBuffer;  69     return strAnsi;  70 }  71  
 72 // reply of the requery 
 73 size_t req_reply(void *ptr, size_t size, size_t nmemb, void *stream)  74 {  75     if (stream == NULL || ptr == NULL || size == 0)  76         return 0;  77  
 78     size_t realsize = size * nmemb;  79     std::string *buffer = (std::string*)stream;  80     if (buffer != NULL)  81  {  82         buffer->append((const char *)ptr, realsize);  83  }  84     return realsize;  85     /*
 86  std::string *str = (std::string*)stream;  87  (*str).append((char*)ptr, size*nmemb);  88  return size * nmemb;  89     */
 90 }  91  
 92 /*
 93 功能:get http數據  94 參數:url:請求字符串。若是請求帶參數數據,直接拼湊到url後面;好比:http://127.0.0.1:8080/api/Accounts/Login?uername=admin&password=123  95 listRequestHeader:請求頭數據列表。  96 bResponseIsWithHeaderData:bool類型,表示響應體中是否包含應答頭數據。true,包含,false,不包含。若是包含的話,應答數據中包含Content-Type,Server等信息。  97 nConnectTimeout:鏈接超時時間,單位爲秒;  98 nTimeout:讀寫數據超時時間,單位爲秒  99 返回值:CURLcode 100 */
101 CURLcode curl_get_req(const std::string &url, std::string &response, std::list<std::string> listRequestHeader, bool bResponseIsWithHeaderData = false, int nConnectTimeout = 10, int nTimeout = 10) 102 { 103     // init curl 
104     CURL *curl = curl_easy_init(); 105     // res code 
106  CURLcode res; 107     if (curl) 108  { 109         // set params 
110         curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // url 111         //curl_easy_setopt(m_curl, CURLOPT_PORT, 8089); //port
112         curl_easy_setopt(curl, CURLOPT_POST, 0); // get reqest 113         //構建HTTP報文頭
114         struct curl_slist* headers = NULL; 115         if (listRequestHeader.size() > 0) 116  { 117             std::list<std::string>::iterator iter, iterEnd; 118             iter = listRequestHeader.begin(); 119             iterEnd = listRequestHeader.end(); 120             for (iter; iter != iterEnd; iter++) 121  { 122                 headers = curl_slist_append(headers, iter->c_str()); 123  } 124             //headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8"); 125             //headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
126             if (headers != NULL) 127  { 128                 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//設置http請求頭信息
129  } 130  } 131         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https 
132         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false 
133         curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); 134  curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); 135  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply); 136         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); 137         curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); 138         if (bResponseIsWithHeaderData) 139  { 140             curl_easy_setopt(curl, CURLOPT_HEADER, 1);//響應體中是否包含了頭信息,好比Content-Type:application/json;charset=UTF-8
141  } 142         curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, nConnectTimeout); // set transport and time out time 
143  curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeout); 144         // start request 
145         res = curl_easy_perform(curl); 146         if (headers != NULL) 147  { 148             curl_slist_free_all(headers); //free the list again
149  } 150  } 151     // release curl 
152  curl_easy_cleanup(curl); 153     return res; 154 } 155  
156 CURLcode curl_get_req_ex(CURL *curl, const std::string &url, std::string &response, std::list<std::string> listRequestHeader, bool bResponseIsWithHeaderData = false, int nConnectTimeout = 10, int nTimeout = 10) 157 { 158     // res code 
159  CURLcode res; 160     if (curl) 161  { 162         // set params 
163  curl_easy_reset(curl); 164         /* enable TCP keep-alive for this transfer */
165         curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); 166         /* keep-alive idle time to 120 seconds */
167         curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L); 168         /* interval time between keep-alive probes: 30 seconds */
169         curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 30L); 170  
171         curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // url 172         //curl_easy_setopt(m_curl, CURLOPT_PORT, 8089); //port
173         curl_easy_setopt(curl, CURLOPT_POST, 0); // get reqest 174         //構建HTTP報文頭
175         struct curl_slist* headers = NULL; 176         if (listRequestHeader.size() > 0) 177  { 178             std::list<std::string>::iterator iter, iterEnd; 179             iter = listRequestHeader.begin(); 180             iterEnd = listRequestHeader.end(); 181             for (iter; iter != iterEnd; iter++) 182  { 183                 headers = curl_slist_append(headers, iter->c_str()); 184  } 185             //headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8"); 186             //headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
187             if (headers != NULL) 188  { 189                 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//設置http請求頭信息
190  } 191  } 192         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https 
193         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false 
194         curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); 195  curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); 196  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply); 197         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); 198         curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); 199         if (bResponseIsWithHeaderData) 200  { 201             curl_easy_setopt(curl, CURLOPT_HEADER, 1);//響應體中是否包含了頭信息,好比Content-Type:application/json;charset=UTF-8
202  } 203         curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, nConnectTimeout); // set transport and time out time 
204  curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeout); 205         // start request 
206         res = curl_easy_perform(curl); 207         if (headers != NULL) 208  { 209             curl_slist_free_all(headers); //free the list again
210  } 211  } 212     return res; 213 } 214  
215 /*
216 功能:post http數據 217 參數:url:請求字符串,好比:http://127.0.0.1:8080/api/Accounts/Login 218 postParams:請求附帶的參數,好比uername=admin&password=123 219 listRequestHeader:請求頭數據列表。 220 bResponseIsWithHeaderData:bool類型,表示響應體中是否包含應答頭數據。true,包含,false,不包含。若是包含的話,應答數據中包含Content-Type,Server等信息。 221 nConnectTimeout:鏈接超時時間,單位爲秒; 222 nTimeout:讀寫數據超時時間,單位爲秒 223 返回值:CURLcode 224 */
225 CURLcode curl_post_req(const std::string &url, const std::string &postParams, std::string &response, std::list<std::string> listRequestHeader, bool bResponseIsWithHeaderData = false, int nConnectTimeout = 10, int nTimeout = 10) 226 { 227     // init curl 
228     CURL *curl = curl_easy_init(); 229     // res code 
230  CURLcode res; 231     if (curl) 232  { 233         // set params 
234         curl_easy_setopt(curl, CURLOPT_POST, 1); // post req 
235         curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // url 236         //curl_easy_setopt(m_curl, CURLOPT_PORT, 8089); //port
237         curl_easy_setopt(curl, CURLOPT_POST, 1); // post reqest 238         //構建HTTP報文頭
239         struct curl_slist* headers = NULL; 240         if (listRequestHeader.size() > 0) 241  { 242             std::list<std::string>::iterator iter, iterEnd; 243             iter = listRequestHeader.begin(); 244             iterEnd = listRequestHeader.end(); 245             for (iter; iter != iterEnd; iter++) 246  { 247                 headers = curl_slist_append(headers, iter->c_str()); 248  } 249             //headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8"); 250             //headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded");
251             if (headers != NULL) 252  { 253                 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//設置http請求頭信息
254  } 255  } 256         else
257  { 258             headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded"); 259             if (headers != NULL) 260  { 261                 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//設置http請求頭信息
262  } 263  } 264         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postParams.c_str()); // params 
265         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https 
266         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false 
267         curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); 268         curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //返回的頭部中有Location(通常直接請求的url沒找到),則繼續請求Location對應的數據 
269  curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); 270  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply); 271         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); 272         curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); 273         if (bResponseIsWithHeaderData) 274  { 275             curl_easy_setopt(curl, CURLOPT_HEADER, 1);//響應體中是否包含了頭信息,好比Content-Type:application/json;charset=UTF-8
276  } 277  curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, nConnectTimeout); 278  curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeout); 279         // start request 
280         res = curl_easy_perform(curl); 281         if (headers != NULL) 282  { 283             curl_slist_free_all(headers); //free the list again
284  } 285  } 286     // release curl 
287  curl_easy_cleanup(curl); 288     return res; 289 } 290  
291 CURLcode curl_post_req_ex(CURL *curl, const std::string &url, const std::string &postParams, std::string &response, std::list<std::string> listRequestHeader, bool bResponseIsWithHeaderData = false, int nConnectTimeout = 10, int nTimeout = 10) 292 { 293     // res code 
294  CURLcode res; 295     if (curl) 296  { 297         // set params
298  curl_easy_reset(curl); 299         /* enable TCP keep-alive for this transfer */
300         curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); 301         /* keep-alive idle time to 120 seconds */
302         curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L); 303         /* interval time between keep-alive probes: 30 seconds */
304         curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 30L); 305  
306         curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // url 307         //curl_easy_setopt(m_curl, CURLOPT_PORT, 8089); //port
308         curl_easy_setopt(curl, CURLOPT_POST, 1); // post reqest 309         //構建HTTP報文頭
310         struct curl_slist* headers = NULL; 311         if (listRequestHeader.size() > 0) 312  { 313             std::list<std::string>::iterator iter, iterEnd; 314             iter = listRequestHeader.begin(); 315             iterEnd = listRequestHeader.end(); 316             for (iter; iter != iterEnd; iter++) 317  { 318                 headers = curl_slist_append(headers, iter->c_str()); 319  } 320             //headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8"); 321             //headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded;charset=UTF-8");
322             if (headers != NULL) 323  { 324                 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//設置http請求頭信息
325  } 326  } 327         else
328  { 329             headers = curl_slist_append(headers, "Content-Type:application/x-www-form-urlencoded"); 330             if (headers != NULL) 331  { 332                 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);//設置http請求頭信息
333  } 334  } 335         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postParams.c_str()); // params 
336         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); // if want to use https 
337         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); // set peer and host verify false 
338         curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); 339         curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //返回的頭部中有Location(通常直接請求的url沒找到),則繼續請求Location對應的數據 
340  curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL); 341  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, req_reply); 342         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&response); 343         curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); 344         if (bResponseIsWithHeaderData) 345  { 346             curl_easy_setopt(curl, CURLOPT_HEADER, 1);//響應體中是否包含了頭信息,好比Content-Type:application/json;charset=UTF-8
347  } 348  curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, nConnectTimeout); 349  curl_easy_setopt(curl, CURLOPT_TIMEOUT, nTimeout); 350         // start request 
351         res = curl_easy_perform(curl); 352         if (headers != NULL) 353  { 354             curl_slist_free_all(headers); //free the list again
355  } 356  } 357     return res; 358 } 359  
360 //實例1
361  curl_global_init(CURL_GLOBAL_ALL); 362     
363     //post獲取數據
364     std::string strResponse = "",strResponseAnsi = ""; 365  strResponse.clear(); 366     CURLcode res = curl_post_req("http://127.0.0.1:8080/api/Accounts/Login", "username=admin&password=123", strResponse); 367     if (res == CURLE_OK) 368  { 369         std::string strToken = ""; 370         strResponseAnsi = Utf8toAscii(strResponse); 371  } 372  
373     //get獲取數據
374  strResponse.clear(); 375     res = curl_get_req("http://127.0.0.1:8080/api/Accounts/Login?username=admin&password=123", strResponse); 376     if (res == CURLE_OK) 377  { 378         int jj = 0; 379  } 380  
381  curl_global_cleanup(); 382 //實例2 383     //post json數據
384     CURL * curl = curl_easy_init(); 385     std::string strResponse = "", strResponseAnsi = ""; 386     char szRequestUrl[256] = { 0 }; 387     CURLcode res = CURLE_OK; 388     sprintf_s(szRequestUrl, "%s/api/GPS/AddOne", "http://127.0.0.1:8080"); 389     std::string strPostParams = ""; 390     try
391  { 392  boost::property_tree::ptree ptroot; 393         ptroot.put("deviceid", "12345678"); 394         ptroot.put<unsigned int>("deviceStatus", 0); 395         ptroot.put<unsigned int>("alarmFlag", 0); 396         ptroot.put("lng", fLongitude); 397         ptroot.put("lat", fLatitude); 398         ptroot.put("speed", 0); 399         ptroot.put("direction", 0); 400         ptroot.put<int>("altitude", 10); 401         ptroot.put("gpsTime", "2018-10-10 12:00:01"); 402  std::stringstream sstream; 403  boost::property_tree::write_json(sstream, ptroot); 404         strPostParams = sstream.str(); 405         bSuccess = true; 406  } 407     catch (boost::property_tree::ptree_error pt) 408  { 409  pt.what(); 410  } 411     if (bSuccess) 412  { 413       std::string strAuthorization = "admin---"; 414         std::string strRequestHeaders = strAuthorization; 415         std::list<std::string> listRequestHeader; 416  listRequestHeader.push_back(strRequestHeaders); 417         listRequestHeader.push_back("Content-Type:application/json;charset=UTF-8"); 418         res = curl_post_req_ex(curl, szRequestUrl, strPostParams, strResponse, listRequestHeader); 419         if (res == CURLE_OK) 420  { 421             bSuccess = true; 422  } 423  } 424 
425 curl_easy_cleanup(curl);

注意事項:

一、http模式測試,使用Postman插件或模擬測試網站 https://www.sojson.com/httpRequest/

二、保持長鏈接,設置選項。
 /* enable TCP keep-alive for this transfer */
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
        /* keep-alive idle time to 120 seconds */
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
        /* interval time between keep-alive probes: 60 seconds */
        curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
        
三、調用libcurl下載,而後使用netstat查看發現有大量的TCP鏈接保持在CLOSE_WAIT狀態
查看libcurl的文檔說明,有這樣一個選項:
CURLOPT_FORBID_REUSE
Pass a long. Set to 1 to make the next transfer explicitly close the connection when done. Normally, libcurl keeps all connections alive when done with one transfer in case a succeeding one follows that can re-use them. This option should be used with caution and only if you understand what it does. Set to 0 to have libcurl keep the connection open for possible later re-use (default behavior).
也就是說,默認狀況下libcurl完成一個任務之後,出於重用鏈接的考慮不會立刻關閉
若是沒有新的TCP請求來重用這個鏈接,那麼只能等到CLOSE_WAIT超時,這個時間默認在7200秒甚至更高,太多的CLOSE_WAIT鏈接會致使性能問題
解決方法:
curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1);
最好再修改一下TCP參數調低CLOSE_WAIT和TIME_WAIT的超時時間

四、libcurl進行異步併發
使用multi接口,multi接口的使用會比easy 接口稍微複雜點,畢竟multi接口是依賴easy接口的,首先粗略的講下其使用流程:curl_multi _init初始化一個multi curl對象,爲了同時進行多個curl的併發訪問,咱們須要初始化多個easy curl對象,使用curl_easy_setopt進行相關設置,而後調用curl_multi _add_handle把easy curl對象添加到multi curl對象中,添加完畢後執行curl_multi_perform方法進行併發的訪問,訪問結束後curl_multi_remove_handle移除相關easy curl對象,curl_easy_cleanup清除easy curl對象,最後curl_multi_cleanup清除multi curl對象。multi接口具體使用方法參考下面連接

https://blog.csdn.net/whui19890911/article/details/79320408

五、請求頭、響應頭多個參數設置。使用curl_slist_append函數一個個參數插入。

參考資料:

libcurl官網:https://curl.haxx.se/libcurl/

vc編譯libcurl:https://www.cnblogs.com/findumars/p/7496122.html

 

curl_errno錯誤碼說明

CURLE_UNSUPPORTED_PROTOCOL (1) – 您傳送給 libcurl 的網址使用了此 libcurl 不支持的協議。 多是您沒有使用的編譯時選項形成了這種狀況(多是協議字符串拼寫有誤,或沒有指定協議 libcurl 代碼)。

CURLE_FAILED_INIT (2) – 很是早期的初始化代碼失敗。 多是內部錯誤或問題。

CURLE_URL_MALFORMAT (3) – 網址格式不正確。

CURLE_COULDNT_RESOLVE_PROXY (5) – 沒法解析代理服務器。 指定的代理服務器主機沒法解析。

CURLE_COULDNT_RESOLVE_HOST (6) – 沒法解析主機。 指定的遠程主機沒法解析。

CURLE_COULDNT_CONNECT (7) – 沒法經過 connect() 鏈接至主機或代理服務器。

CURLE_FTP_WEIRD_SERVER_REPLY (8) – 在鏈接到 FTP 服務器後,libcurl 須要收到特定的回覆。 此錯誤代碼表示收到了不正常或不正確的回覆。 指定的遠程服務器可能不是正確的 FTP 服務器。

CURLE_REMOTE_ACCESS_DENIED (9) – 咱們沒法訪問網址中指定的資源。 對於 FTP,若是嘗試更改成遠程目錄,就會發生這種狀況。

CURLE_FTP_WEIRD_PASS_REPLY (11) – 在將 FTP 密碼發送到服務器後,libcurl 須要收到正確的回覆。 此錯誤代碼表示返回的是意外的代碼。

CURLE_FTP_WEIRD_PASV_REPLY (13) – libcurl 沒法從服務器端收到有用的結果,做爲對 PASV 或 EPSV 命令的響應。 服務器有問題。

CURLE_FTP_WEIRD_227_FORMAT (14) – FTP 服務器返回 227 行做爲對 PASV 命令的響應。若是 libcurl 沒法解析此行,就會返回此代碼。

CURLE_FTP_CANT_GET_HOST (15) – 在查找用於新鏈接的主機時出現內部錯誤。

CURLE_FTP_COULDNT_SET_TYPE (17) – 在嘗試將傳輸模式設置爲二進制或 ascii 時發生錯誤。

CURLE_PARTIAL_FILE (18) – 文件傳輸尺寸小於或大於預期。當服務器先報告了一個預期的傳輸尺寸,而後所傳送的數據與先前指定尺寸不相符時,就會發生此錯誤。

CURLE_FTP_COULDNT_RETR_FILE (19) – ‘RETR’ 命令收到了不正常的回覆,或完成的傳輸尺寸爲零字節。

CURLE_QUOTE_ERROR (21) – 在向遠程服務器發送自定義 「QUOTE」 命令時,其中一個命令返回的錯誤代碼爲 400 或更大的數字(對於 FTP),或以其餘方式代表命令沒法成功完成。

CURLE_HTTP_RETURNED_ERROR (22) – 如 果 CURLOPT_FAILONERROR 設置爲 TRUE,且 HTTP 服務器返回 >= 400 的錯誤代碼,就會返回此代碼。 (此錯 誤代碼之前又稱爲 CURLE_HTTP_NOT_FOUND。)

CURLE_WRITE_ERROR (23) – 在向本地文件寫入所收到的數據時發生錯誤,或由寫入回調 (write callback) 向 libcurl 返回了一個錯誤。

CURLE_UPLOAD_FAILED (25) – 沒法開始上傳。 對於 FTP,服務器一般會拒絕執行 STOR 命令。錯誤緩衝區一般會提供服務器對此問題的說明。 (此錯誤代碼之前又稱爲 CURLE_FTP_COULDNT_STOR_FILE。)

CURLE_READ_ERROR (26) – 讀取本地文件時遇到問題,或由讀取回調 (read callback) 返回了一個錯誤。

CURLE_OUT_OF_MEMORY (27) – 內存分配請求失敗。此錯誤比較嚴重,若發生此錯誤,則代表出現了很是嚴重的問題。

CURLE_OPERATION_TIMEDOUT (28) – 操 做超時。 已達到根據相應狀況指定的超時時間。 請注意: 自 Urchin 6.6.0.2 開始,超時時間能夠自行更改。 要指定遠程日誌下載超時, 請打開 urchin.conf 文件,取消如下行的註釋標記:

#DownloadTimeout: 30 

CURLE_FTP_PORT_FAILED (30) – FTP PORT 命令返回錯誤。 在沒有爲 libcurl 指定適當的地址使用時,最有可能發生此問題。 請參閱 CURLOPT_FTPPORT。

CURLE_FTP_COULDNT_USE_REST (31) – FTP REST 命令返回錯誤。若是服務器正常,則應當不會發生這種狀況。

CURLE_RANGE_ERROR (33) – 服務器不支持或不接受範圍請求。

CURLE_HTTP_POST_ERROR (34) – 此問題比較少見,主要由內部混亂引起。

CURLE_SSL_CONNECT_ERROR (35) – 同時使用 SSL/TLS 時可能會發生此錯誤。您能夠訪問錯誤緩衝區查看相應信息,其中會對此問題進行更詳細的介紹。多是證書(文件格式、路徑、許可)、密碼及其餘因素致使了此問題。

CURLE_FTP_BAD_DOWNLOAD_RESUME (36) – 嘗試恢復超過文件大小限制的 FTP 鏈接。

CURLE_FILE_COULDNT_READ_FILE (37) – 沒法打開 FILE:// 路徑下的文件。緣由極可能是文件路徑沒法識別現有文件。 建議您檢查文件的訪問權限。

CURLE_LDAP_CANNOT_BIND (38) – LDAP 沒法綁定。LDAP 綁定操做失敗。

CURLE_LDAP_SEARCH_FAILED (39) – LDAP 搜索沒法進行。

CURLE_FUNCTION_NOT_FOUND (41) – 找不到函數。 找不到必要的 zlib 函數。

CURLE_ABORTED_BY_CALLBACK (42) – 由回調停止。 回調向 libcurl 返回了 「abort」。

CURLE_BAD_FUNCTION_ARGUMENT (43) – 內部錯誤。 使用了不正確的參數調用函數。

CURLE_INTERFACE_FAILED (45) – 界 面錯誤。 指定的外部界面沒法使用。 請經過 CURLOPT_INTERFACE 設置要使用哪一個界面來處理外部鏈接的來源 IP 地址。 (此錯誤代 碼之前又稱爲 CURLE_HTTP_PORT_FAILED。)

CURLE_TOO_MANY_REDIRECTS (47) – 重定向過多。 進行重定向時,libcurl 達到了網頁點擊上限。請使用 CURLOPT_MAXREDIRS 設置上限。

CURLE_UNKNOWN_TELNET_OPTION (48) – 沒法識別以 CURLOPT_TELNETOPTIONS 設置的選項。 請參閱相關文檔。

CURLE_TELNET_OPTION_SYNTAX (49) – telnet 選項字符串的格式不正確。

CURLE_PEER_FAILED_VERIFICATION (51) – 遠程服務器的 SSL 證書或 SSH md5 指紋不正確。

CURLE_GOT_NOTHING (52) – 服務器未返回任何數據,在相應狀況下,未返回任何數據就屬於出現錯誤。

CURLE_SSL_ENGINE_NOTFOUND (53) – 找不到指定的加密引擎。

CURLE_SSL_ENGINE_SETFAILED (54) – 沒法將選定的 SSL 加密引擎設爲默認選項。

CURLE_SEND_ERROR (55) – 沒法發送網絡數據。

CURLE_RECV_ERROR (56) – 接收網絡數據失敗。

CURLE_SSL_CERTPROBLEM (58) – 本地客戶端證書有問題

CURLE_SSL_CIPHER (59) – 沒法使用指定的密鑰

CURLE_SSL_CACERT (60) – 沒法使用已知的 CA 證書驗證對等證書

CURLE_BAD_CONTENT_ENCODING (61) – 沒法識別傳輸編碼

CURLE_LDAP_INVALID_URL (62) – LDAP 網址無效

CURLE_FILESIZE_EXCEEDED (63) – 超過了文件大小上限

CURLE_USE_SSL_FAILED (64) – 請求的 FTP SSL 級別失敗

CURLE_SEND_FAIL_REWIND (65) – 進行發送操做時,curl 必須迴轉數據以便從新傳輸,但迴轉操做未能成功

CURLE_SSL_ENGINE_INITFAILED (66) – SSL 引擎初始化失敗

CURLE_LOGIN_DENIED (67) – 遠程服務器拒絕 curl 登陸(7.13.1 新增功能)

CURLE_TFTP_NOTFOUND (68) – 在 TFTP 服務器上找不到文件

CURLE_TFTP_PERM (69) – 在 TFTP 服務器上遇到權限問題

CURLE_REMOTE_DISK_FULL (70) – 服務器磁盤空間不足

CURLE_TFTP_ILLEGAL (71) – TFTP 操做非法

CURLE_TFTP_UNKNOWNID (72) – TFTP 傳輸 ID 未知

CURLE_REMOTE_FILE_EXISTS (73) – 文件已存在,沒法覆蓋

CURLE_TFTP_NOSUCHUSER (74) – 運行正常的 TFTP 服務器不會返回此錯誤

CURLE_CONV_FAILED (75) – 字符轉換失敗

CURLE_CONV_REQD (76) – 調用方必須註冊轉換回調

CURLE_SSL_CACERT_BADFILE (77) – 讀取 SSL CA 證書時遇到問題(多是路徑錯誤或訪問權限問題)

CURLE_REMOTE_FILE_NOT_FOUND (78) – 網址中引用的資源不存在

CURLE_SSH (79) – SSH 會話中發生沒法識別的錯誤

CURLE_SSL_SHUTDOWN_FAILED (80) – 沒法終止 SSL 鏈接
---------------------
做者:byxdaz
來源:CSDN
原文:https://blog.csdn.net/byxdaz/article/details/81869881

相關文章
相關標籤/搜索