废话不多说,代码中使用了两种https客户端的实现方式。
完整代码:https://github.com/satadriver/openssl-TLS_SSL-sample
#include<windows.h>#include<WinSock.h>#include"../include/openssl\ssl.h"#include"../include/openssl\err.h"#pragmacomment(lib,"ws2_32.lib")#pragmacomment(lib,"../lib/libeay32.lib")#pragmacomment(lib,"../lib/ssleay32.lib")#defineHTTPS_PORT443DWORDBIOSendRecvData(sockaddr_in stBaiduPassPortAddr,char*pSendData,intiSendSize,char*pRecvData,intiRecvSize){//ERR_load_crypto_strings();//ERR_load_SSL_strings();//OPENSSL_add_all_algorithms_noconf();//如果系统平台不支持自动进行随机数种子的设置,这里应该进行设置(seed PRNG)SSL_CTX*ctxClient=SSL_CTX_new(SSLv3_client_method());//通常应该在这里设置一些验证路径和模式等,因为这里没有设置,所以该例子可以跟使用任意CA签发证书的任意服务器建立连接BIO*stBio=BIO_new_ssl_connect(ctxClient);SSL*sslClient=FALSE;intiRet=BIO_get_ssl(stBio,&sslClient);if(sslClient==FALSE){fprintf(stderr,"Can't locate SSL pointer\n");//ERR_print_errors_fp(stderr);//SSL_free(sslClient);SSL_CTX_free(ctxClient);BIO_free_all(stBio);returnFALSE;}/* 不需要任何重试请求*/iRet=SSL_set_mode(sslClient,SSL_MODE_AUTO_RETRY);//这里你可以添加对SSL的其它一些设置charszBioConnectAddrFormat[]="%s:%u";charszBioConnectAddr[64];intiLen=wsprintfA(szBioConnectAddr,szBioConnectAddrFormat,inet_ntoa(stBaiduPassPortAddr.sin_addr),HTTPS_PORT);iRet=BIO_set_conn_hostname(stBio,szBioConnectAddr);//"passport.baidu.com"//BIO * out=BIO_new_fp(stdout,BIO_NOCLOSE);if(BIO_do_handshake(stBio)<=0){//SSL_free(sslClient);SSL_CTX_free(ctxClient);fprintf(stderr,"Error connecting to server\n");ERR_print_errors_fp(stderr);returnFALSE;}X509*stCert=SSL_get_peer_certificate(sslClient);char*strServerName=X509_NAME_oneline(X509_get_subject_name(stCert),0,0);OPENSSL_free(strServerName);strServerName=X509_NAME_oneline(X509_get_issuer_name(stCert),0,0);OPENSSL_free(strServerName);X509_free(stCert);iRet=BIO_write(stBio,pSendData,iSendSize);if(iRet<=0){//SSL_free(sslClient);SSL_CTX_free(ctxClient);BIO_free_all(stBio);returnFALSE;}char*pRecvPtr=pRecvData;iRet=BIO_read(stBio,pRecvPtr,iRecvSize);if(iRet<=0){//SSL_free(sslClient);SSL_CTX_free(ctxClient);BIO_free_all(stBio);returnFALSE;}while(iRet==1){pRecvPtr++;iRet=BIO_read(stBio,pRecvPtr,iRecvSize);}if(iRet>0){*(pRecvPtr+iRet)=0;}BIO_free_all(stBio);SSL_CTX_free(ctxClient);//SSL_free(sslClient);//BIO_free(out);returnTRUE;}DWORDSendAndRecvHttpsPacket(sockaddr_in stBaiduPassPortAddr,char*pSendData,intiSendSize,char*pRecvData,intiRecvSize){SOCKET sockClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(sockClient==INVALID_SOCKET){returnFALSE;}intiRet=connect(sockClient,(sockaddr*)&stBaiduPassPortAddr,sizeof(sockaddr_in));if(iRet==INVALID_SOCKET){closesocket(sockClient);returnFALSE;}SSL_CTX*pctxClient=SSL_CTX_new(SSLv23_client_method());if(pctxClient==0){iRet=GetLastError();closesocket(sockClient);returnFALSE;}SSL*pSSLClient=SSL_new(pctxClient);if(pSSLClient==0){closesocket(sockClient);returnFALSE;}iRet=SSL_set_fd(pSSLClient,sockClient);if(iRet<=0){iRet=GetLastError();closesocket(sockClient);returnFALSE;}iRet=SSL_connect(pSSLClient);if(iRet<=0){iRet=GetLastError();returnFALSE;}iRet=SSL_write(pSSLClient,pSendData,iSendSize);if(iRet<=0){iRet=GetLastError();returnFALSE;}char*pRecvBuf=pRecvData;intiSize=iRecvSize;do{iRet=SSL_read(pSSLClient,pRecvBuf,1);if(iRet>0){pRecvBuf++;iSize--;}}while(iRet>0);*pRecvBuf=0;SSL_free(pSSLClient);SSL_CTX_free(pctxClient);closesocket(sockClient);return(pRecvBuf-pRecvData);}DWORDBIOServerSample(){BIO*sbio,*bbio,*acpt,*out;intlen;chartmpbuf[1024];SSL_CTX*ctx;SSL*ssl;ERR_load_crypto_strings();ERR_load_SSL_strings();OpenSSL_add_all_algorithms();//Might seed PRNG herectx=SSL_CTX_new(SSLv23_server_method());if(!SSL_CTX_use_certificate_file(ctx,"server.pem",SSL_FILETYPE_PEM)||!SSL_CTX_use_PrivateKey_file(ctx,"server.pem",SSL_FILETYPE_PEM)||!SSL_CTX_check_private_key(ctx)){fprintf(stderr,"Error setting up SSL_CTX\n");ERR_print_errors_fp(stderr);return0;}//Might do other things here like setting verify locations and//DH and/or RSA temporary key callbacks// New SSL BIO setup as serversbio=BIO_new_ssl(ctx,0);BIO_get_ssl(sbio,&ssl);if(!ssl){fprintf(stderr,"Can't locate SSL pointer\n");// whatever ...}// Don't want any retriesSSL_set_mode(ssl,SSL_MODE_AUTO_RETRY);// Create the buffering BIObbio=BIO_new(BIO_f_buffer());//Add to chainsbio=BIO_push(bbio,sbio);acpt=BIO_new_accept("433");// By doing this when a new connection is established// we automatically have sbio inserted into it. The// BIO chain is now 'swallowed' by the accept BIO and// will be freed when the accept BIO is freed.BIO_set_accept_bios(acpt,sbio);out=BIO_new_fp(stdout,BIO_NOCLOSE);// Setup accept BIOif(BIO_do_accept(acpt)<=0){fprintf(stderr,"Error setting up accept BIO\n");ERR_print_errors_fp(stderr);return0;}// Now wait for incoming connectionif(BIO_do_accept(acpt)<=0){fprintf(stderr,"Error in connection\n");ERR_print_errors_fp(stderr);return0;}// We only want one connection so remove and free// accept BIO//sbio=BIO_pop(acpt);BIO_free_all(acpt);if(BIO_do_handshake(sbio)<=0){fprintf(stderr,"Error in SSL handshake\n");ERR_print_errors_fp(stderr);return0;}BIO_puts(sbio,"HTTP/1.0 200 OK\r\nContent-type: text/plain\r\n\r\n");BIO_puts(sbio,"\r\nConnection Established\r\nRequest headers:\r\n");BIO_puts(sbio,"--------------------------------------------------\r\n");for(;;){len=BIO_gets(sbio,tmpbuf,1024);if(len<=0)break;BIO_write(sbio,tmpbuf,len);BIO_write(out,tmpbuf,len);// Look for blank line signifying end of headersif((tmpbuf[0]=='\r')||(tmpbuf[0]=='\n'))break;}BIO_puts(sbio,"--------------------------------------------------\r\n");BIO_puts(sbio,"\r\n");// Since there is a buffering BIO present we had better flush itBIO_flush(sbio);BIO_free_all(sbio);returnTRUE;}int__stdcallWinMain(__in HINSTANCE hInstance,__in_opt HINSTANCE hPrevInstance,__in LPSTR lpCmdLine,__inintnShowCmd){WSAData wsa;intret=WSAStartup(0x0202,&wsa);if(ret){returnFALSE;}SSL_library_init();SSL_load_error_strings();OpenSSL_add_all_algorithms();charszdata[0x4000];for(inti=0;i<sizeof(szdata);i++){szdata[i]='a';}szdata[0]='/';szdata[1]=0;hostent*lphost=gethostbyname("www.baidu.com");DWORD lpip=*(DWORD*)(lphost->h_addr_list);DWORD ip=*(DWORD*)lpip;sockaddr_in sa={0};sa.sin_family=AF_INET;sa.sin_port=ntohs(443);sa.sin_addr.S_un.S_addr=ip;charszrecv[0x4000];ret=BIOSendRecvData(sa,szdata,lstrlenA(szdata),szrecv,sizeof(szdata));//ret=SendAndRecvHttpsPacket(sa,szdata,0x10000,szrecv,0x10000);// SOCKET s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);// if (s == INVALID_SOCKET)// {// return FALSE;// }returnTRUE;}