HTTP/HTTPS客户端源码示例

环境:  zlib-1.2.8  openssl-1.0.1g  curl-7.36

Author:  Kagula

LastUpdateDate: 2016-05-09

阅读前提:CMake工具的基本使用、配置openssl-1.0.1g 开发环境

编译zlib库

下载zlib-1.2.8.tar.gz并解压缩到" D:\SDK\zlib-1.2.8",使用CMake工具生成zlib.sln,在Visual Studio2013中打开并编译即可。

编译curl-7.36.0

假设Open SSL已经安装到“D:\SDK\openssl-1.0.1g”,先设置下面的环境变量

OPENSSL_LIBRARIES=D:\SDK\openssl-1.0.1g\out32

OPENSSL_ROOT_DIR=D:\SDK\openssl-1.0.1g

从http://curl.haxx.se/下载curl-7.36.0.zip并解压缩到“D:\SDK\curl-7.36.0”启动CMake工具Configure,分别设置LIB_EAY_RELEASE和SSL_EAY_RELEASE变量为“D:\SDK\openssl-1.0.1g\out32\libeay32.lib”,“D:\SDK\openssl-1.0.1g\out32\ssleay32.lib”,产生sln文件后打开,为里面的curl工程项目添加“USE_MANUAL”宏定义,然后build里面的4个项目成功。

为项目添加链接库libcurl_imp.lib  , 把libcurl.dll文件复制到C++项目路径下,否则程序运行会提示找不到动态链接库。

下面是HTTP/HTTPS客户端示例

如何使用

#include <iostream>
#include <string>using namespace std;#include "httpclient.h"int main(int argc, char *argv[])
{string response;//loginkagula::network::CHttpClient client;int nR = client.Post("https://lijun:8443/escortcashbox/main/login.do","data={\"version\":\"1.0.0.0\",\"user\":\"admin\",\"password\":\"123\"}",                         response,true,"d:\cookie.txt","D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/tomcat7.pem","D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/client_all.pem","123456");cout << nR << endl <<response << endl;//upload png file/*std::map<std::string,std::string> mapFields;std::map<std::string,std::vector<std::string>> mapFiles;mapFields["data"] = "{\"version\":\"1.0.0.0\",\"socialid\":\"1012\",\"realname\":\"realnamevalue\",\"portrait\":\"protraitvalue\",\"fingerid\":\"fingeridvalue\",\"groupid\":\"123\"}";std::vector<std::string> vecFile(2);vecFile[0] = "d:\\b.png";vecFile[1] = "image/png";mapFiles["portraitFile"] = vecFile;nR = client.MultipartFormdata("https://lijun:8443/escortcashbox/main/escortStaffAdd.do",mapFields,mapFiles,response,"d:\cookie.txt","D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/tomcat7.pem","D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/client_all.pem","123456");cout << nR << endl << response << endl;
*///download png filenR = client.GetFile("https://lijun:8443/escortcashbox/upload/img/20160527_110514_679_426.png","d:/ee.png","d:\cookie.txt","D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/tomcat7.pem","D:/workspace_qt/build-escortcashbox_c-Mingw32-Debug/debug/client_all.pem","123456");cout << nR << endl;return 0;
}

HttpClient.h封装好的头文件

//HttpClient.h源代码清单
#ifndef _HTTPCLIENT_H_
#define _HTTPCLIENT_H_#include <string>
#include <map>
#include <vector>/*
Title: Get Response from Web Server by HTTP/HTTPS method.
Environment:
Windows 7SP1, Windows 8.1, Windows 10
QT Creator 3.5.1, Visual Studio 2013 Update1, Visual Studio 2013 Update5
libcurl 7.36.0, libcurl 7.46.0, Qt 5.6, MSYS2 64bits gcc 5.3.0
Last Update: 2016-05-27
Remark:
[1]如果要在多线程方式下同时调用多个CHttpClient实例,需要在App初始化的时候调用kagula::network::Init();在App结束的时候调用kagula::network::Cleanup();
[2]编译libcurl必须打开zlib标志,并且把OpenSSL也链进去。Reference:
curl_eay_setopt manual
http://www.helplib.net/s/linux.die/65_2740/man-3-curl-easy-setopt.shtml
C++ cout format
http://www.cnblogs.com/devymex/archive/2010/09/06/1818754.html
*/namespace kagula
{namespace network{void Init();void Cleanup();class CHttpClient{public:CHttpClient(void);~CHttpClient(void);public:/*** @brief HTTP/HTTPS POST/GET请求* @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com* @param strPost 输入参数,使用如下格式para1=val1¶2=val2&…* @param strCookie 输入参数,Cookie文件名,例如 d:\temp\cookie.txt*                          如果为空,不启用Cookie.* @param strResponse 输出参数,返回的内容* @param bPost 是否Post方式发送请求,默认Post方式发送请求。* @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.* @param pClientCalPath 输入参数,为客户端证书的路径.如果输入为NULL,则不验证客户端证书的有效性.* @param pClientCalPassword 输入参数,为客户端证书的存取密码.* @return 返回是否Post成功* 0  成功* 7  无法连接* 28 超时* 58 服务端验证客户端证书失败。* 60 客户端验证服务端证书失败。*/int Post(const char* pUrl,const char* pPost,std::string &strResponse,bool bPost,const char* pCookie,const char* pCaPath = NULL,const char* pClientCalPath = NULL,const char* pClientCalPassword = NULL);int MultipartFormdata(const char *pUrl,const std::map<std::string,std::string> & mapFields,const std::map<std::string,std::vector<std::string>> & mapFiles,std::string & strResponse,const char *pCookie,const char * pCaPath = NULL,const char * pClientCalPath = NULL,const char * pClientCalPassword = NULL);int GetFile(const char* pUrl,const char* pLocalFullPath,const char* pCookie,const char* pCaPath = NULL,const char* pClientCalPath = NULL,const char* pClientCalPassword = NULL);public:void SetDebug(bool bDebug);std::string getMsgInChinese(int code);private:bool m_bDebug;bool PrintCookies(void* curl, std::string& strOut);};}
}
#endif

源文件清单

//HttpClient.cpp源代码清单
#include "HttpClient.h"
#include <iostream>
#include <curl/curl.h>
#include <iomanip>
#include <sstream>#ifdef WIN32
#pragma comment(lib,"libcurl_imp.lib")
#endifnamespace kagula
{namespace network{CHttpClient::CHttpClient(void) :m_bDebug(false){}CHttpClient::~CHttpClient(void){}bool CHttpClient::PrintCookies(void* curl, std::string& strOut){std::ostringstream ostr;CURLcode res;struct curl_slist *cookies;res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);if (res != CURLE_OK) {ostr << "Curl curl_easy_getinfo failed:" << curl_easy_strerror(res) << std::endl;strOut = ostr.str();return false;}const struct curl_slist *nc = cookies;int i = 1;ostr << "Cookies, curl knows:" << std::endl;while (nc) {ostr << "[" << i++ << "]: " << nc->data << std::endl;nc = nc->next;}return true;}static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *){if (itype == CURLINFO_TEXT){//printf("[TEXT]%s\n", pData);}else if (itype == CURLINFO_HEADER_IN){printf("[HEADER_IN]%s\n", pData);}else if (itype == CURLINFO_HEADER_OUT){printf("[HEADER_OUT]%s\n", pData);}else if (itype == CURLINFO_DATA_IN){printf("[DATA_IN]%s\n", pData);}else if (itype == CURLINFO_DATA_OUT){printf("[DATA_OUT]%s\n", pData);}return 0;}size_t OnWriteData_Post(void* buffer, size_t size, size_t nmemb, void* lpVoid){std::string* str = reinterpret_cast<std::string*>(lpVoid);if (NULL == str || NULL == buffer){return -1;}char* pData = reinterpret_cast<char*>(buffer);str->append(pData, size * nmemb);return nmemb;}size_t OnWriteData_MultipartFormdata( void *inBuffer, size_t size, size_t nmemb, void *outBuffer ){int len = size * nmemb;char *temp = new char[len+1];memcpy(temp,inBuffer,len);temp[len]=0;reinterpret_cast<std::string *>(outBuffer)->append(temp);delete temp;return len;}size_t OnWriteData_GetFile(void *inBuffer, int size, int nmemb, std::string &content){long len = size * nmemb;std::string temp((char *)inBuffer, len);content += temp;return len;}std::string CHttpClient::getMsgInChinese(int code){switch(code){case 0:return "通讯成功";case 7:return "服务器连接失败。";case 28:return "连接超时。";case 58:return "服务端验证客户端证书失败。";case 60:return "客户端验证服务端证书失败。";default:return "";}}int CHttpClient::Post(const char* pUrl,const char* pPost,std::string & strResponse,bool bPost,const char* pCookie,const char* pCaPath,const char* pClientCalPath,const char* pClientCalPassword){strResponse = "";CURLcode res;CURL* curl = curl_easy_init();if (NULL == curl){return CURLE_FAILED_INIT;}if (m_bDebug){curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);}curl_easy_setopt(curl, CURLOPT_URL, pUrl);if(bPost){curl_easy_setopt(curl, CURLOPT_POST, 1);curl_easy_setopt(curl, CURLOPT_POSTFIELDS, pPost);}curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_Post);curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);if (pCookie!=0){curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)pCookie);curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)pCookie);}if (NULL == pCaPath){curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);//需要在编译curl的时候,一同编译zlib标志。要不然找不到这个标志.//当然前提是你已经编译完成zlib.//发出接受gzip压缩内容的请求,如果服务器支持gzip内容,会返回压缩后的数据。//如果Http服务器不支持gzip encoding也不影响libcurl正常工作。//接受数据的时候,如果返回的是压缩数据,libcurl会自动解压数据。curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip");}else{//缺省情况就是PEM,所以无需设置,另外支持DER//curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);//服务端需要认证客户端的真实性,即双向认证。if(pClientCalPath!=NULL){curl_easy_setopt(curl,CURLOPT_SSLCERT, pClientCalPath);curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD, pClientCalPassword);curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE, "PEM");curl_easy_setopt(curl,CURLOPT_SSLKEY, pClientCalPath);curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD, pClientCalPassword);curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE, "PEM");}}            //curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);//Web服务器一般会重定向链接,比如访问http:/xxx/x1.do自动转到http:/xxx/x2.do//所以一定要设置CURLOPT_FOLLOWLOCATION为1,否则重定向后的数据不会返回。curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,1);res = curl_easy_perform(curl);curl_easy_cleanup(curl);return res;}int CHttpClient::MultipartFormdata(const char *pUrl,const std::map<std::string,std::string> & mapFields,const std::map<std::string,std::vector<std::string>> & mapFiles,std::string & strResponse,const char *pCookie,const char * pCaPath,const char * pClientCalPath,const char * pClientCalPassword){CURL *curl;CURLcode res;curl = curl_easy_init();strResponse ="";curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_MultipartFormdata);//write_datacurl_easy_setopt(curl, CURLOPT_WRITEDATA, &strResponse);struct curl_httppost *formpost = 0;struct curl_httppost *lastptr  = 0;//std::map<std::string,std::string>::const_iterator iterFields = mapFields.begin();while(iterFields!=mapFields.end()){//curl_formadd(&formpost, &lastptr,CURLFORM_COPYNAME,"data",CURLFORM_COPYCONTENTS, pData,CURLFORM_END);curl_formadd(&formpost, &lastptr,CURLFORM_COPYNAME,iterFields->first.c_str(),CURLFORM_COPYCONTENTS, iterFields->second.c_str(),CURLFORM_END);iterFields++;}std::map<std::string,std::vector<std::string>>::const_iterator iterFiles = mapFiles.begin();while(iterFiles!=mapFiles.end()){//"image/jpeg","image/png"//curl_formadd(&formpost, &lastptr,CURLFORM_PTRNAME, "portraitFile", CURLFORM_FILE, pImageFileName,CURLFORM_CONTENTTYPE, "image/png", CURLFORM_END);curl_formadd(&formpost, &lastptr,CURLFORM_PTRNAME,iterFiles->first.c_str(), CURLFORM_FILE,iterFiles->second[0].c_str(),CURLFORM_CONTENTTYPE,iterFiles->second[1].c_str(), CURLFORM_END);iterFiles++;}//curl_easy_setopt(curl, CURLOPT_URL, pUrl);curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);if (pCookie!=0){curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)pCookie);curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)pCookie);}//单向认证用if(pCaPath!=0){curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);}//服务端需要认证客户端的真实性,即双向认证。if(pClientCalPath!=0 && pClientCalPassword!=0){curl_easy_setopt(curl,CURLOPT_SSLCERT, pClientCalPath);curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD, pClientCalPassword);curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE, "PEM");curl_easy_setopt(curl,CURLOPT_SSLKEY, pClientCalPath);curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD, pClientCalPassword);curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE, "PEM");}res = curl_easy_perform(curl);curl_easy_cleanup(curl);curl_formfree(formpost);return res;}int CHttpClient::GetFile(const char* pUrl,const char* pLocalFullPath,const char* pCookie,const char* pCaPath,const char* pClientCalPath,const char* pClientCalPassword){CURL *curl = NULL;CURLcode code;char bufError[CURL_ERROR_SIZE];std::string content;long retcode = 0;code = curl_global_init(CURL_GLOBAL_DEFAULT);if (code != CURLE_OK){//printf("Failed to global init default [%d]\n", code);return -100;}curl = curl_easy_init();if (curl == NULL){//printf("Failed to create CURL connection\n");return -200;}code = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, bufError);if (code != CURLE_OK){//printf("Failed to set error buffer [%d]\n", code);return code;}//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);code = curl_easy_setopt(curl, CURLOPT_URL, pUrl);if (code != CURLE_OK){//printf("Failed to set URL [%s]\n", error);goto _END;}code = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);if (code != CURLE_OK){//printf("Failed to set redirect option [%s]\n", error);goto _END;}code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_GetFile);if (code != CURLE_OK){//printf("Failed to set writer [%s]\n", error);goto _END;}code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);if (code != CURLE_OK){//printf("Failed to set write data [%s]\n", error);goto _END;}if (pCookie!=0){curl_easy_setopt(curl, CURLOPT_COOKIEFILE, (void *)pCookie);curl_easy_setopt(curl, CURLOPT_COOKIEJAR, (void *)pCookie);}//单向认证用if(pCaPath!=0){curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);}//服务端需要认证客户端的真实性,即双向认证。if(pClientCalPath!=0 && pClientCalPassword!=0){curl_easy_setopt(curl,CURLOPT_SSLCERT, pClientCalPath);curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD, pClientCalPassword);curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE, "PEM");curl_easy_setopt(curl,CURLOPT_SSLKEY, pClientCalPath);curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD, pClientCalPassword);curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE, "PEM");}code = curl_easy_perform(curl);if (code != CURLE_OK){//printf("Failed to get '%s' [%s]\n", URL, error);goto _END;}code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &retcode);if ((code == CURLE_OK) && retcode == 200){double length = 0;code = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &length);//printf("%d", retcode);FILE * file = fopen(pLocalFullPath, "wb");fseek(file, 0, SEEK_SET);fwrite(content.c_str(), 1, (size_t)length, file);fclose(file);code =  CURLE_OK;goto _END;}_END:curl_easy_cleanup(curl);return code;}///void CHttpClient::SetDebug(bool bDebug){m_bDebug = bDebug;}void Init(){//the function is not thread safe.curl_global_init(CURL_GLOBAL_ALL);}void Cleanup(){curl_global_cleanup();}}
}

注意:

[1]MSys64 Mingw32 QtCreator 32位C++程序 配置libcurl
假设Msys64是安装在C盘默认路径上
第一步:在Msys64中查询可用的curl包
pacman -Ss curl

第二步:安装
pacman -S mingw-w64-i686-curl

第三步:在.pro文件下加入下面的代码
LIBS += C:\msys64\mingw32\lib\libcurl.dll.a
INCLUDEPATH += C:\msys64\mingw32\include
最后:编译链接依赖libcurl的项目成功。

[2]如何产生cer文件

https原理及tomcat配置https方法
http://jingyan.baidu.com/article/a948d6515d3e850a2dcd2ee6.html

[3]单向认证,让客户端信任服务端证书

第一步:
双击从服务端keystore中导出的cer文件可以导入证书。
windows下“certmgr.msc”命令可以进入证书管理。
自己制作的证书导入到Win7后默认在“中级证书颁发机构”->“证书”节点里。

第二步:
需要把你做的证书拖到“受信任的根证书颁发机构”->“证书”节点中去,否则
浏览器会提醒“此网站出具的安全证书不是由受信任的证书颁发机构颁发的”等类似错误。
chrome需要重启,IE直接刷新页面,就不会出现警告了。

注意:
数字证书转换cer---pem 
在Msys2 Shell中确保安装好openssl.
在Msys2 Shell中使用openssl命令后进入openssl提示符,输入下面的命令
x509 -inform der -in d:/MyServerSecurity/tomcat7.cer -out d:/MyServerSecurity/tomcat7.pem

[4]双向认证,让服务端信任客户端的证书

相当于“Https单向认证”,添加了“服务端验证客户端身份真实性”的动作。
需要注意的是:服务端的密钥库参数“CN”必须与服务端的IP地址相同,否则会报错,客户端的任意。
如果服务端的CN为lijun,则客户端不能为lijun,即这两个不能是同一个名字。

第一步:客户端生成证书(用于服务端验证客户端)
keytool -validity 365 -genkeypair -v -alias kagula -keyalg RSA -storetype PKCS12 -keystore D:\MyClientSecurity\kagulakey.p12 -storepass 123456 -keypass 123456
kagula为证书的名称,D:\MyClientSecurity\kagulakey.p12证书的存放位置。

第二步:证书格式转为cer文件。
keytool -export -v -alias kagula -keystore D:\MyClientSecurity\kagulakey.p12 -storetype PKCS12 -storepass 123456 -rfc -file D:\MyClientSecurity\kagulakey.cer
kagula为证书的名称,D:\MyClientSecurity\kagulakey.p12证书的存放位置,123456证书密码,D:\MyClientSecurity\kagulakey.cer导出的文件。

第三步:添加到(或新建)一个keystore文件
keytool -import -v -alias kagula -file D:\MyClientSecurity\kagulakey.cer -keystore D:\MyServerSecurity\tomcat7_client.keystore -storepass 123456
tomcat7_client.keystore如果不存在就会新建一个keystore,如果存在会添加到已经存在的keystore中。

第四步:查看keystore文件中的内容
keytool -list -keystore D:\MyServerSecurity\tomcat7_client.keystore

第五步:修改tomcat7中的server.xml文件
原单向认证的配置如下
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" 
               keystoreFile="D:\\MyServerSecurity\\tomcat7.keystore" keystorePass="123456"/>
               
               
现在修改后,如下
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="true" sslProtocol="TLS"
               keystoreFile="D:\\MyServerSecurity\\tomcat7.keystore" keystorePass="123456"
  truststoreFile="D:\\MyServerSecurity\\tomcat7_client.keystore" truststorePass="123456"/>           
添加了最后一行属性使它指向客户端证书,并把clientAuth属性从false改为true。

第六步(可选):
Step6-1:
测试Windows下的Chrome是否还能访问服务器,果然刷新浏览器后
“https://lijun:8443/escortcashbox/main/aboutUs.do”返回错误信息
Step6-2:
测试libcurl是否还能访问服务器,现在libcurl返回7(无法连接服务器)的错误信息。

最后一步-让Windows下的Chrome和IE能访问服务端:
双击D:\MyClientSecurity\kagulakey.p12文件,“不需要添加到受信任的根证书机构”结点,直接导入证书即可。
默认在certmgr.msc命令,“个人”->“证书”节点下。

最后一步-让libcurl能访问服务端:
使用msys64打开openssl命令行工具
#客户端个人证书的公钥
openssl>pkcs12 -in D:\MyClientSecurity\myclientkey.p12 -out D:\MyClientSecurity\client_publickey.pem -nokeys
也许如果在当前command shell下能找到openssl.exe也可以用下面的命令
“openssl pkcs12 -in D:\MyClientSecurity\myclientkey.p12 -out D:\MyClientSecurity\client_publickey.pem -nokeys”

#客户端个人证书的私钥
openssl pkcs12 -in D:\MyClientSecurity\myclientkey.p12 -out D:\MyClientSecurity\client_privatekey.pem -nocerts -nodes

#也可以转换为公钥与私钥合二为一的文件;     客户端公钥与私钥,一起存在all.pem中
openssl>pkcs12 -in D:\MyClientSecurity\kagulakey.p12 -out D:\MyClientSecurity\client_all.pem -nodes

1、使用client_publickey.pem + client_privatekey.pem  (未在win console shell下测试)
curl -k --cert client_publickey.pem --key D:\MyClientSecurity\client_privatekey.pem https://lijun:8443/escortcashbox/main/aboutUs.do

2、可以在Msys64 Shell中执行curl命令(如果已经安装了curl)...使用all.pem
curl -k --cert /d/MyClientSecurity/client_all.pem https://lijun:8443/escortcashbox/main/aboutUs.do

下面是双向认证的参考资料
SSL——Secure Sockets Layer
http://www.blogjava.net/icewee/archive/2012/06/04/379947.html

补充阅读资料

使用libcurl实现上传文件到FTP服务器

http://blog.csdn.net/lee353086/article/details/5823145

使用libcurl下载http://www.baidu.com/img/baidu.gif示例

http://www.cppblog.com/qiujian5628/archive/2008/06/28/54873.html

libcurl的使用总结(一)

http://www.vimer.cn/2010/03/libcurl%E7%9A%84%E4%BD%BF%E7%94%A8%E6%80%BB%E7%BB%93%EF%BC%88%E4%B8%80%EF%BC%89.html

PHP的curl实现get,post 和 cookie

http://www.tsingpost.com/articles/201403/525.html

Libcurl的编译_HTTP/HTTPS客户端源码示例相关推荐

  1. libcurl使用多线程下载大文件源码示例!

    使用libcurl多线程下载大文件的基本思想: 首选打开文件,将文件等分为指定的片段,使用http range下载,一个线程下载一个片段,当线程下载片段时,它们将数据写到打开文件的指定位置,类似BT文 ...

  2. ubuntu编译内核_鸿蒙源码下载并编译

    第一章 下载源码并编译 1.1 在Ubuntu中安装开发环境 如果你是从头看文档,并且按照文档操作,那么你已经按照<5.2 安装Ubuntu软件>下载并运行了这个脚本:Configurin ...

  3. WordPress Blog Android客户端源码分析(一)

    一直想找一个大型的Android开源项目进行分析,由于自身和导师课程需要选择了wordpress的Android客户端源码进行学习和解读.源码github官方下载地址:开源项目地址.分析源码的最佳手段 ...

  4. 编译hadoop2.2.0源码时报错

    编译hadoop2.2.0源码时, mvn install -DskipTests 报错: [ERROR] COMPILATION ERROR : [INFO] ------------------- ...

  5. Ubuntu 12.04(64位)下载并编译 Android 4.1 源码[只有2条命令]

    2019独角兽企业重金招聘Python工程师标准>>> Ubuntu 12.04(64位)下载并编译 Android 4.1 源码[只有2条命令] ================= ...

  6. idea 编译spring_《Spring源码解析(二)》构建 Spring5 源码工程,开启研读Spring源码之路...

    Spring5 源码下载注意事项 首先你的 JDK 需要升级到 1.8 以上.Spring3.0 开始,Spring 源码采用 github 托管,不再提供官网下载 链接.这里不做过多赘述,大家可自行 ...

  7. mysql 5.7 源码编译安装_mysql-5.7.*源码编译安装

    mysql-5.7.*源码编译安装 系统安装条件 官方文档说明:http://dev.mysql.com/doc/refman/5.7/en/source-installation.html 1> ...

  8. Ubuntu12.04编译Android4.0.1源码全过程-----附wubi安装ubuntu编译android源码硬盘空间不够的问题解决

    Ubuntu12.04编译Android4.0.1源码全过程-----附wubi安装ubuntu编译android源码硬盘空间不够的问题解决 参考文章: (1)Ubuntu12.04编译Android ...

  9. 编译FriendlyDesktop的Uboot源码、内核,修改开机图片logo

    1. 安装依赖包 参照官网wiki教程 - 12章节:Nanopi 教程wiki 安装以下依赖包. sudo apt-get -y install bison g++-multilib git gpe ...

最新文章

  1. 【廖雪峰python入门笔记】tuple_创建单元素
  2. 二 RHEL7.2下的Docker配置
  3. 日本語のマナーを学びましょう
  4. Python网络编程—(TCP、UDP区别)
  5. LeetCode - Palindrome Number
  6. 翻转单词顺序和左旋转字符串
  7. VSS(2005)中如何强行签入文件
  8. window.open使用中遇到的问题
  9. [NOIP2005] 提高组 洛谷P1051 谁拿了最多奖学金
  10. Java程序员都要懂得知识点:反射
  11. 基于.NET平台的分层架构实战(八)——数据访问层的第二种实现:SQLServer+存储过程...
  12. python将网页保存为图片_「保存网页为图片」如何将整个网页保存为图片? - seo实验室...
  13. IBM推出企业信息安全框架
  14. 【迷失岛游戏框架开发个人每集总结(第四期)】
  15. 有道云笔记不同步_有道云笔记无法同步如何处理?笔记无法同步解决方法介绍...
  16. No binary rubies available for: osx/10.8/x86_64/ruby-1.9.2-p320解决
  17. 计算机毕业设计Python+django 宠物领养中心小程序(源码+系统+mysql数据库+Lw文档)
  18. html做万用表效果,一种万用表的制作方法
  19. 用python写一个程序控制其它软件_程序员:利用Python实现可控制肉鸡的反向Shell...
  20. AKABEiSOFT2经典作品推荐 車輪の国、向日葵の少女( 攻略、汉化、特典、PSP转换器)

热门文章

  1. 北风网人工智能就业班
  2. NYOJ47 过河问题
  3. 2020年安全简报(2月)
  4. Dos安装pyinstaller时报错Non-UTF-8 code starting with '\x90' in file pip3.6.exe on line 1
  5. 《链家网技术架构的演进之路》读后感
  6. Python读取dat文件格式的数据
  7. pythonpptx库api干果加_使用Python操作Evernote API
  8. 老闪创业那些事儿(54)——闷骚的设计师
  9. eyoucms添加发布内容
  10. postman密码错误找回时没有任何反应||postman密码找回