环境:
win7 + vs2013 + openssl-1.0.2f
openssl-1.0.2f 采用 lib 编译
注意:
设置 工程的包含目录 到 编译好的openssl 的 \include\openssl目录下
在 vc++ 目录 包含目录中填入
$(ProjectDir)\openssl( 这个可能不是你的目录名 )\include
代码 一部分来自 openssl 自带的demo 一部分直接从 msdn 上面剪下来
注意关闭 项目==》属性==》SDL 检查 以忽略gethostbyname
错误
// HttpsCliDemo.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#pragma comment(lib,"./openssl/lib/libeay32.lib")
#pragma comment(lib,"./openssl/lib/ssleay32.lib")
#define HOST "www.mail.163.com"
// 手工构造最简单的请求包
// Ps.
// 如果没有此字段,请求成功后不会立刻断开
// Connection:closed\r\n
#define REQUEST "GET / HTTP/1.1\r\nHost: mail.163.com\r\nConnection:closed\r\n\r\n"
int _tmain(int argc, _TCHAR* argv[])
{
int nStarup, nErr = 0;
WSADATA wsaData;
SOCKET sConnectSocket = -1;
char szResponseBuf[40960];
__try
{
// 1. 初始化WSA 和 Openssl Lib
nStarup = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (nStarup != NO_ERROR) {
wprintf(L" WSAStartup function failed with error: %d\n", nStarup);
__leave;
}
SSLeay_add_ssl_algorithms();
SSL_load_error_strings();
// 2. 创建套接字并连接服务器
sConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sConnectSocket == INVALID_SOCKET) {
wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
__leave;
}
hostent* host = (hostent*)gethostbyname(HOST);
struct in_addr **addr_list = (struct in_addr **)host->h_addr_list;
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr(inet_ntoa(*addr_list[0]));
clientService.sin_port = htons(443);
nStarup = connect(sConnectSocket, (SOCKADDR *)& clientService, sizeof(clientService));
if (nStarup == SOCKET_ERROR)
{
wprintf(L"connect function failed with error: %ld\n", WSAGetLastError());
nStarup = closesocket(sConnectSocket);
if (nStarup == SOCKET_ERROR)
{
wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
}
sConnectSocket = 0;
WSACleanup();
__leave;
}
// 3. 初始化加密模式生成ssl套接字
SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
if (!ctx)
{
wprintf(L"SSL_CTX_new failed\n");
nStarup = closesocket(sConnectSocket);
if (nStarup == SOCKET_ERROR)
{
wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
}
sConnectSocket = 0;
WSACleanup();
__leave;
}
SSL *ssl = SSL_new(ctx);
if (!ssl)
{
SSL_CTX_free(ctx);
wprintf(L"SSL_new failed\n");
nStarup = closesocket(sConnectSocket);
if (nStarup == SOCKET_ERROR)
{
wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
}
sConnectSocket = 0;
WSACleanup();
__leave;
}
// 4. 绑定 原套接字到 ssl套接字
nErr = SSL_set_fd(ssl, sConnectSocket);
// 5. 使用ssl套件字建立连接
nErr = SSL_connect(ssl);
// 6. Request https server
nErr = SSL_write(ssl, REQUEST, strlen(REQUEST));
wprintf(L"\n===============读取网页==================");
// 7. 由于控制台缓存区不够可能打印不完整
do
{
ZeroMemory(szResponseBuf, sizeof(szResponseBuf));
nErr = SSL_read(ssl, szResponseBuf, sizeof(szResponseBuf));
if (nErr > 0) {
printf("%s", szResponseBuf);
}
else
{
break;
}
} while (true);
// 8. 释放
SSL_free(ssl);
SSL_CTX_free(ctx);
nStarup = closesocket(sConnectSocket);
if (nStarup == SOCKET_ERROR)
{
wprintf(L"closesocket function failed with error: %ld\n", WSAGetLastError());
}
sConnectSocket = 0;
WSACleanup();
wprintf(L"\n=======================================\n");
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
wprintf(L"find exception!\n");
}
return 0;
}