基于 openssl + vs2013 https服务端 Demo
2016-03-04 16:06
447 查看
环境:
win7 + vs2013 + openssl-1.0.2fopenssl-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附件
相关文章推荐
- Unity多人游戏和网络功能(一) 概述和基本概念
- 最详细的 HTTPS 科普扫盲帖
- android网络通信之socket教程实例汇总
- NPOI 导出Excel图片 (网络)
- Unity3d多人游戏与网络功能(四)-状态机同步与远程动作
- 关于最近遇到的一些iOS面试题<2>答案来自网络
- 安卓多线程编程系列3:使用handler和message下载网络图片
- TCP协议三次握手四次挥手过程
- arm qt自启+网络自动获取ip地址
- centos---无线上网的电脑所安装的虚拟机网络设置
- C#实现http协议下载的断点续传
- The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar
- 如何更高效地使用 OkHttp
- Android学习之网络请求库Volley
- 最详细的 HTTPS 科普扫盲帖
- iOS真实网络 监测 RealReachability
- 二进制流文流输出成zip
- 安卓多线程编程系列2:异步任务的使用之使用异步任务带有进度的横向滚动条下载网络图片
- 页面优化——减少HTTP请求数
- 检测TCP端口占用状态的函数