Files
--hp-socket-TCP--ssl--/Client-Native/README.md

359 lines
7.9 KiB
Markdown
Raw Normal View History

2026-01-23 08:39:07 +08:00
# 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
**用途:** 学习和对比
**状态:** 完成并可运行