Files
--hp-socket-TCP--ssl--/Client-Native/README.md
2026-01-23 08:39:07 +08:00

359 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Client-Native 说明文档
## 项目简介
**Client-Native** 是一个纯OpenSSL+Winsock实现的SSL客户端**不使用HP-Socket库**。
这个项目的目的是:
1. 展示底层SSL通信的实现细节
2. 对比HP-Socket封装的便利性
3. 帮助理解SSL/TLS协议的工作原理
## 功能对比
### Client使用HP-Socket
```cpp
// 简单的几行代码就能实现SSL客户端
CClientListener listener;
CSSLClientPtr client(&listener);
// 初始化SSLHP-Socket封装
client->SetupSSLContextByMemory(...);
// 连接服务器HP-Socket封装
client->Start(address, port);
// 发送数据HP-Socket封装
client->Send(data, length);
```
### Client-Native纯OpenSSL+Winsock
```cpp
// 需要手动处理很多底层细节
// 1. 初始化Winsock
WSAStartup(...);
// 2. 创建socket
socket = socket(AF_INET, SOCK_STREAM, ...);
// 3. 连接服务器
connect(socket, ...);
// 4. 创建SSL上下文
SSL_CTX* ctx = SSL_CTX_new(TLS_client_method());
// 5. 加载证书和私钥
SSL_CTX_use_certificate(...);
SSL_CTX_use_PrivateKey(...);
// 6. 创建SSL对象
SSL* ssl = SSL_new(ctx);
// 7. 绑定socket
SSL_set_fd(ssl, socket);
// 8. SSL握手
SSL_connect(ssl);
// 9. 发送数据
SSL_write(ssl, data, length);
// 10. 接收数据
SSL_read(ssl, buffer, size);
// 11. 清理资源
SSL_shutdown(ssl);
SSL_free(ssl);
closesocket(socket);
WSACleanup();
```
**结论HP-Socket的封装极大简化了开发工作**
## 实现的功能
### ✅ 已实现
- Winsock初始化
- TCP socket连接
- SSL上下文创建和配置
- 从内存加载证书和私钥
- SSL双向认证SSL_VM_PEER
- SSL握手
- 加密数据发送
- 加密数据接收
- 非阻塞数据接收检查
- 交互式命令界面
- 资源清理
### 🎯 核心代码
#### 1. 初始化SSL环境
```cpp
bool InitializeSSL()
{
// 创建SSL上下文
g_ssl_ctx = SSL_CTX_new(TLS_client_method());
// 设置验证模式
SSL_CTX_set_verify(g_ssl_ctx, SSL_VERIFY_PEER, nullptr);
// 加载CA证书
X509* ca_cert = LoadCertFromMemory(g_c_lpszCAPemCert);
X509_STORE* store = SSL_CTX_get_cert_store(g_ssl_ctx);
X509_STORE_add_cert(store, ca_cert);
// 加载客户端证书和私钥
SSL_CTX_use_certificate(...);
SSL_CTX_use_PrivateKey(...);
return true;
}
```
#### 2. 连接到服务器
```cpp
bool ConnectToServer()
{
// 创建TCP socket
g_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// 连接到服务器
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(DEFAULT_PORT);
inet_pton(AF_INET, DEFAULT_ADDRESS, &serverAddr.sin_addr);
connect(g_socket, (sockaddr*)&serverAddr, sizeof(serverAddr));
// 创建SSL对象并绑定socket
g_ssl = SSL_new(g_ssl_ctx);
SSL_set_fd(g_ssl, (int)g_socket);
// 执行SSL握手
SSL_connect(g_ssl);
return true;
}
```
#### 3. 发送和接收数据
```cpp
// 发送
bool SendData(const std::string& data)
{
int sent = SSL_write(g_ssl, data.c_str(), data.length());
return sent > 0;
}
// 接收
void ReceiveData()
{
char buffer[1024];
int received = SSL_read(g_ssl, buffer, sizeof(buffer) - 1);
if (received > 0) {
buffer[received] = '\0';
// 处理接收到的数据
}
}
```
## 使用说明
### 编译
```powershell
cd "E:\开发\C_C++\hp-socket-6.0.4\hp-socket-6.0.7-src\Windows\Demo\TestEcho-SSL-Console"
& "D:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" Client-Native\Client-Native.vcxproj /p:Configuration=Debug /p:Platform=x64
```
### 运行
1. 先启动Server
```
Windows\Demo\Debug\x64\TestEcho-SSL-Console-Server.exe
```
2. 再启动Client-Native
```
Windows\Demo\Debug\x64\TestEcho-SSL-Console-Client-Native.exe
```
3. 在Client-Native中按 `1` 发送"hello",服务器会回复"hello!"
### 命令
- `1` - 发送 "hello" 到服务器
- `q` - 退出程序
## 技术要点
### 1. OpenSSL API使用
#### 证书加载(从内存)
```cpp
X509* LoadCertFromMemory(const char* certPem)
{
BIO* bio = BIO_new_mem_buf(certPem, -1);
X509* cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
BIO_free(bio);
return cert;
}
```
#### 私钥加载(带密码)
```cpp
EVP_PKEY* LoadKeyFromMemory(const char* keyPem, const char* password)
{
BIO* bio = BIO_new_mem_buf(keyPem, -1);
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, (void*)password);
BIO_free(bio);
return pkey;
}
```
#### SSL握手
```cpp
SSL_connect(g_ssl); // 阻塞调用,直到握手完成
```
### 2. 非阻塞I/O
为了不阻塞主循环,接收数据使用非阻塞模式:
```cpp
// 设置为非阻塞
u_long mode = 1;
ioctlsocket(g_socket, FIONBIO, &mode);
// 尝试读取(不会阻塞)
int received = SSL_read(g_ssl, buffer, size);
// 恢复阻塞模式
mode = 0;
ioctlsocket(g_socket, FIONBIO, &mode);
```
### 3. 错误处理
OpenSSL的错误处理
```cpp
void PrintSSLError(const char* msg)
{
unsigned long err = ERR_get_error();
char errBuf[256];
ERR_error_string_n(err, errBuf, sizeof(errBuf));
std::cout << "[错误] " << msg << ": " << errBuf << std::endl;
}
```
### 4. 资源管理
必须按顺序清理资源:
```cpp
void Cleanup()
{
if (g_ssl) {
SSL_shutdown(g_ssl); // 关闭SSL连接
SSL_free(g_ssl); // 释放SSL对象
}
if (g_socket != INVALID_SOCKET) {
closesocket(g_socket); // 关闭socket
}
if (g_ssl_ctx) {
SSL_CTX_free(g_ssl_ctx); // 释放SSL上下文
}
WSACleanup(); // 清理Winsock
}
```
## 依赖项
### 头文件
- `<winsock2.h>` - Windows Socket API
- `<openssl/ssl.h>` - SSL/TLS功能
- `<openssl/err.h>` - 错误处理
- `<openssl/x509.h>` - X.509证书
- `<openssl/bio.h>` - BIO抽象
- `<openssl/pem.h>` - PEM格式
### 库文件
- `ws2_32.lib` - Winsock库
- `libssl.lib` - OpenSSL SSL库
- `libcrypto.lib` - OpenSSL加密库
- `crypt32.lib` - Windows加密API库
### 路径配置
```
Include: E:\开发\C_C++\hp-socket-6.0.4\hp-socket-6.0.7-src\Windows\Dependent\openssl\14x\x64\include
Library: E:\开发\C_C++\hp-socket-6.0.4\hp-socket-6.0.7-src\Windows\Dependent\openssl\14x\x64\lib
```
## 学习价值
### 对比学习
通过Client-Native项目你可以学到
1. **底层实现细节**
- Socket编程
- SSL/TLS握手过程
- 证书加载和验证
- 加密数据传输
2. **HP-Socket的价值**
- 封装了复杂的底层细节
- 提供简洁的API
- 自动处理错误和资源管理
- 跨平台支持
3. **SSL/TLS协议理解**
- 握手过程
- 证书链验证
- 密钥交换
- 数据加密/解密
### 代码行数对比
| 项目 | 代码行数 | 复杂度 |
|------|----------|--------|
| ClientHP-Socket | ~273行 | 低 |
| Client-Native原生 | ~450行+ | 中高 |
**结论使用HP-Socket可以减少40%+的代码量!**
## 常见问题
### Q: 为什么要创建这个项目?
A: 为了学习SSL底层实现理解HP-Socket的封装价值。
### Q: 实际项目应该用哪个?
A: 实际项目强烈推荐使用HP-SocketClient-Native仅用于学习。
### Q: Client-Native的性能如何
A: 性能与HP-Socket相当底层都是OpenSSL但HP-Socket提供了更多优化和错误处理。
### Q: 可以用Client-Native连接生产环境吗
A: 不建议。生产环境应使用成熟的库如HP-Socket而不是自己实现。
### Q: 如何添加更多功能?
A: 参考HP-Socket的实现逐步添加
- 异步I/O
- 连接池
- 断线重连
- 心跳检测
- 数据缓冲
## 总结
**Client-Native项目是一个很好的学习工具**,它帮助你理解:
- SSL/TLS通信的底层实现
- HP-Socket封装的价值
- 网络编程的复杂性
但对于**实际项目**请使用HP-Socket或其他成熟的网络库
---
**创建日期:** 2026年1月13日
**作者:** AI Assistant
**用途:** 学习和对比
**状态:** 完成并可运行