废话不多说,代码中使用了两种https客户端的实现方式。
#include <windows.h>
#include <WinSock.h>#pragma comment(lib,"ws2_32.lib")
#include "../include/openssl\ssl.h"
#include "../include/openssl\err.h"#pragma comment ( lib, "../lib/libeay32.lib" )
#pragma comment ( lib, "../lib/ssleay32.lib" )#define HTTPS_PORT 443DWORD BIOSendRecvData(sockaddr_in stBaiduPassPortAddr,char * pSendData,int iSendSize,char * pRecvData,int iRecvSize)
{//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;int iRet = 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);return FALSE;}/* 不需要任何重试请求*/iRet = SSL_set_mode(sslClient,SSL_MODE_AUTO_RETRY);//这里你可以添加对SSL的其它一些设置char szBioConnectAddrFormat[] = "%s:%u";char szBioConnectAddr[64];int iLen = 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);return FALSE;}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);return FALSE;}char * pRecvPtr = pRecvData;iRet = BIO_read(stBio,pRecvPtr,iRecvSize);if (iRet <= 0){//SSL_free(sslClient);SSL_CTX_free(ctxClient);BIO_free_all(stBio);return FALSE;}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);return TRUE;
}DWORD SendAndRecvHttpsPacket(sockaddr_in stBaiduPassPortAddr,char * pSendData,int iSendSize,char * pRecvData,int iRecvSize)
{SOCKET sockClient = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if (sockClient == INVALID_SOCKET){return FALSE;}int iRet = connect(sockClient,(sockaddr*)&stBaiduPassPortAddr,sizeof(sockaddr_in));if (iRet == INVALID_SOCKET){closesocket(sockClient);return FALSE;}SSL_CTX * pctxClient = SSL_CTX_new( SSLv23_client_method() );if (pctxClient == 0){iRet = GetLastError();closesocket(sockClient);return FALSE;}SSL * pSSLClient = SSL_new(pctxClient);if (pSSLClient == 0){closesocket(sockClient);return FALSE;}iRet = SSL_set_fd(pSSLClient,sockClient);if (iRet <= 0){iRet = GetLastError();closesocket(sockClient);return FALSE;}iRet = SSL_connect(pSSLClient);if (iRet <= 0){iRet = GetLastError();//return FALSE;}iRet = SSL_write(pSSLClient,pSendData,iSendSize);if (iRet <= 0){iRet = GetLastError();//return FALSE;}char * pRecvBuf = pRecvData;int iSize = 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);
}/*
DWORD BIOServerSample()
{BIO *sbio, *bbio, *acpt, *out;int len;char tmpbuf[1024];SSL_CTX *ctx;SSL *ssl;ERR_load_crypto_strings();ERR_load_SSL_strings();OpenSSL_add_all_algorithms();//Might seed PRNG here ctx = 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);return 0;}//Might do other things here like setting verify locations and//DH and/or RSA temporary key callbacks// New SSL BIO setup as server sbio=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 retries SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);// Create the buffering BIO bbio = BIO_new(BIO_f_buffer());//Add to chain sbio = 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 BIO if(BIO_do_accept(acpt) <= 0) {fprintf(stderr, "Error setting up accept BIO\n");ERR_print_errors_fp(stderr);return 0;}// Now wait for incoming connection if(BIO_do_accept(acpt) <= 0) {fprintf(stderr, "Error in connection\n");ERR_print_errors_fp(stderr);return 0;}// 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);return 0;}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 it BIO_flush(sbio);BIO_free_all(sbio);return TRUE;
}
*/int __stdcall WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd ){WSAData wsa;int ret = WSAStartup(0x0202,&wsa);if (ret ){return FALSE;}SSL_library_init( ); SSL_load_error_strings( );OpenSSL_add_all_algorithms();char szdata[0x4000];for (int i =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;char szrecv[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;// }return TRUE;
}