您的位置:首页 > 理论基础 > 计算机网络

基于 openssl + vs2013 https服务端 Demo

2016-03-04 16:06 447 查看

环境:

win7 + vs2013 + openssl-1.0.2f

openssl-1.0.2f 采用 lib 编译

注意:

设置 工程的包含目录 到 编译好的openssl 的 \include\openssl目录下

在 vc++ 目录 包含目录中填入

$(ProjectDir)\openssl( 这个可能不是你的目录名 )\include

代码 一部分来自 openssl 自带的demo 一部分直接从 msdn 上面剪下来

主要看个思路。

这个代码唯一的功能就是,浏览器 输入 https://127.0.0.1:27015之后,浏览器 返回一个 200 ok

// HttpSvrDemo.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib,"Ws2_32.lib")
#pragma comment(lib,"User32.lib")
#pragma comment(lib,"Advapi32.lib")
#pragma comment(lib,"Gdi32.lib")
#include <openssl/ssl.h>
#pragma comment(lib,"./openssl/lib/libeay32.lib")
#pragma comment(lib,"./openssl/lib/ssleay32.lib")

#pragma warning(disable: 4996)

#define CERTF   "server.crt"
#define KEYF    "server.key.unsecure"

// 实际上 我更想用 goto ,但是怕有些强迫症受不了
#define _OBSESSION

#ifdef  _OBSESSION
#define  ERROR_HANDLE(); break;
#else
#define ERROR_HANDLE();  goto __ERROR_xseda65412;
#define ERROR_FLAGE();  __ERROR_xseda65412:
#endif

// 这是一个 https 服务端 Demo
int _tmain(int argc, _TCHAR* argv[])
{
// 参考 OpenSSl 自带Demo
// 位于 Openssl_Src 的 demos\ssl 下 的 serv.cpp
WSADATA wsaData;
sockaddr_in service = { 0 };
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET AcceptSocket = INVALID_SOCKET;
#ifdef  _OBSESSION
do
{
#endif

// 1.初始化 WSA 相关函数
int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (err != 0)
{
/* Tell the user that we could not find a usable */
/* Winsock DLL.                                  */
printf("WSAStartup failed with error: %d\n", err);
return -1;
}

// 2.初始化静态库 加载错误字符 加载算法库
SSL_library_init();
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();

// 3.绑定本地端口并监听 ---- 摘自 MSDN
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET)
{
wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
ERROR_HANDLE();
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(27015);

int iResult = bind(ListenSocket, (SOCKADDR *)& service, sizeof(service));

if (iResult == SOCKET_ERROR)
{
wprintf(L"bind function failed with error %d\n", WSAGetLastError());
ERROR_HANDLE();
}

if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR)
{
wprintf(L"listen function failed with error: %d\n", WSAGetLastError());
ERROR_HANDLE();
}
wprintf(L"Listening on socket...\n");

// 4.等待建立连接
while (TRUE)
{
__try
{
AcceptSocket = accept(ListenSocket, NULL, NULL);
if (AcceptSocket == INVALID_SOCKET)
{
wprintf(L"accept failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return -1;
}
else
{
wprintf(L"Client connected.\n");
}

// 4.1将套接字与证书绑定
const SSL_METHOD *meth = SSLv23_server_method();
SSL_CTX* ctx = SSL_CTX_new(meth);
if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0)
{
wprintf(L"SSL_CTX_use_certificate_file failed.\n");
closesocket(AcceptSocket);
continue;
}

if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0)
{
wprintf(L"SSL_CTX_use_PrivateKey_file failed.\n");
closesocket(AcceptSocket);
continue;
}
if (!SSL_CTX_check_private_key(ctx)) {
wprintf(L"Private key does not match the certificate public key\n");
closesocket(AcceptSocket);
continue;
}
SSL* ssl = SSL_new(ctx);
SSL_set_fd(ssl, AcceptSocket);
if (SSL_accept(ssl) == -1)
{
closesocket(AcceptSocket);
continue;
}

// 4.2从SSL套接字读取数据
char  buf[4096] = { 0 };
if (SSL_read(ssl, buf, 4095) <= 0)
{
__leave;
}
printf("%s\n", buf);

// 4.3往SSL套接字写入数据
char *szTemp = "HTTP/1.1 200 OK\r\nServer: bfe/1.0.8.14\r\nDate: Mon, 29 Feb 2016 06:21:46 GMT\r\nContent-Type: text/html\r\nContent-Length: 70\r\nConnection: keep-alive\r\n\r\n<html>\r\n<head><title>200 Ok</title></head><body> 200 OK </body></html>";
int nCount = strlen(szTemp);
int nRet = 0;
do
{
nRet += SSL_write(ssl, szTemp, nCount);
if (nRet >= nCount)
{
break;
}

} while (true);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{

}
closesocket(AcceptSocket);
AcceptSocket = INVALID_SOCKET;
}

#ifdef  _OBSESSION
}while (FALSE);
#else
ERROR_FLAGE();
#endif

// 5.结束退出 测试一下  浏览器 输入 https://127.0.0.1:27015 // 由于没有导入根证书,所以会弹出安全警告
__try{
if (ListenSocket != INVALID_SOCKET)
{
closesocket(ListenSocket);
ListenSocket = INVALID_SOCKET;
}
if (AcceptSocket != INVALID_SOCKET)
{
closesocket(AcceptSocket);
AcceptSocket = INVALID_SOCKET;
}
WSACleanup();
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// 留块地方 方便扩展
exit(-1);
}
return 0;
}


Demo附件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: