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

472 lines
17 KiB
Markdown
Raw Permalink 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 架构设计文档
## 🏗️ 类图 (Class Diagram)
```
┌─────────────────────────────┐
│ <<static class>> │
│ CertificateConfig │
├─────────────────────────────┤
│ + GetClientCertificate() │
│ + GetClientPrivateKey() │
│ + GetCACertificate() │
│ + GetKeyPassword() │
└─────────────────────────────┘
│ uses
┌─────────────────────────────┐ ┌─────────────────────────────┐
│ CertificateManager │ │ SSLClientConnection │
├─────────────────────────────┤ ├─────────────────────────────┤
│ - (no state) │ │ - m_sslContext: SSL_CTX* │
├─────────────────────────────┤ │ - m_ssl: SSL* │
│ + LoadCertificateFromMemory()│◄───────┤ - m_socket: SOCKET │
│ + LoadPrivateKeyFromMemory()│ uses │ - m_isConnected: bool │
│ + PrintSSLError() │ │ - m_certManager: CertMgr │
└─────────────────────────────┘ ├─────────────────────────────┤
△ │ + Initialize() │
│ uses │ + Connect() │
│ │ + Send() │
│ │ + Receive() │
│ │ + Disconnect() │
┌─────────────────────────────┐ │ + IsConnected() │
│ main() │ │ + GetCipherSuite() │
│ │ ├─────────────────────────────┤
│ [Application Entry Point] │───────>│ - InitializeWinsock() │
│ │ uses │ - Cleanup() │
└─────────────────────────────┘ └─────────────────────────────┘
```
## 📊 模块关系图
```
main.cpp
├──► SSLClientConnection (主要依赖)
│ │
│ ├──► CertificateManager (内部依赖)
│ │ │
│ │ └──► OpenSSL API
│ │
│ └──► Winsock2 API
└──► CertificateConfig (直接依赖)
```
## 🔄 对象生命周期
```
┌────── main() starts ──────┐
│ │
│ ┌──────────────────────┐ │
│ │ SSLClientConnection │ │ <── 创建对象(栈上)
│ │ │ │
│ │ ┌────────────────┐ │ │
│ │ │ CertManager │ │ │ <── 自动创建成员对象
│ │ └────────────────┘ │ │
│ │ │ │
│ │ [Initialize] │ │ <── 分配SSL资源
│ │ └─> SSL_CTX* │ │
│ │ └─> 加载证书 │ │
│ │ │ │
│ │ [Connect] │ │ <── 分配Socket/SSL
│ │ └─> SOCKET │ │
│ │ └─> SSL* │ │
│ │ └─> SSL握手 │ │
│ │ │ │
│ │ [Send/Receive] │ │ <── 数据传输
│ │ └─> SSL_write() │ │
│ │ └─> SSL_read() │ │
│ │ │ │
│ │ [~Destructor] │ │ <── 自动清理
│ │ └─> SSL_free() │ │
│ │ └─> closesocket()│ │
│ │ └─> SSL_CTX_free│ │
│ └──────────────────────┘ │
│ │
└────── main() ends ────────┘
(自动析构,无需手动清理)
```
## 🎯 设计模式应用
### 1. RAII (Resource Acquisition Is Initialization)
```cpp
class SSLClientConnection {
public:
SSLClientConnection() // 构造函数 - 初始化状态
: m_sslContext(nullptr)
, m_ssl(nullptr)
, m_socket(INVALID_SOCKET)
, m_isConnected(false)
{}
~SSLClientConnection() // 析构函数 - 自动清理资源
{
Cleanup(); // 释放SSL、Socket等资源
}
// 禁止拷贝(避免资源重复释放)
SSLClientConnection(const SSLClientConnection&) = delete;
SSLClientConnection& operator=(const SSLClientConnection&) = delete;
};
使用:
{
SSLClientConnection client; // 自动调用构造函数
client.Initialize(...);
client.Connect(...);
// ...
} // ← 离开作用域,自动调用析构函数清理
```
### 2. Static Factory (静态工厂)
```cpp
class CertificateConfig {
public:
// 静态方法,无需实例化
static const char* GetClientCertificate() {
return g_clientCert;
}
private:
// 私有构造函数,防止实例化
CertificateConfig() = default;
~CertificateConfig() = default;
};
使用:
const char* cert = CertificateConfig::GetClientCertificate(); // 直接调用
```
### 3. Manager Pattern (管理器模式)
```cpp
class CertificateManager {
public:
// 无状态的工具方法
X509* LoadCertificateFromMemory(const char* certPem);
EVP_PKEY* LoadPrivateKeyFromMemory(const char* keyPem, ...);
static void PrintSSLError(const char* message);
};
使用:
CertificateManager mgr;
X509* cert = mgr.LoadCertificateFromMemory(certData);
```
### 4. Facade Pattern (外观模式)
```cpp
// SSLClientConnection 提供简化的接口
// 隐藏底层 OpenSSL + Winsock 的复杂性
class SSLClientConnection {
public:
// 简单易用的接口
bool Initialize(...); // 内部处理 SSL_CTX、证书加载等
bool Connect(...); // 内部处理 socket、SSL握手等
bool Send(...); // 内部处理 SSL_write
int Receive(...); // 内部处理 SSL_read
private:
// 隐藏复杂的内部实现
bool InitializeWinsock();
void Cleanup();
// ...
};
```
## 📐 架构层次
```
┌─────────────────────────────────────────┐
│ 应用层 (Application Layer) │ ← main.cpp
│ - 用户交互 │
│ - 命令处理 │
│ - 主循环控制 │
└─────────────────────────────────────────┘
↓ uses
┌─────────────────────────────────────────┐
│ 业务层 (Business Layer) │ ← SSLClientConnection
│ - SSL连接管理 │
│ - 数据发送/接收 │
│ - 连接状态管理 │
└─────────────────────────────────────────┘
↓ uses
┌─────────────────────────────────────────┐
│ 工具层 (Utility Layer) │ ← CertificateManager
│ - 证书加载 │
│ - 错误处理 │
│ - 通用工具 │
└─────────────────────────────────────────┘
↓ uses
┌─────────────────────────────────────────┐
│ 数据层 (Data Layer) │ ← CertificateConfig
│ - 证书数据 │
│ - 配置数据 │
└─────────────────────────────────────────┘
↓ uses
┌─────────────────────────────────────────┐
│ 系统层 (System Layer) │
│ - OpenSSL API │
│ - Winsock2 API │
│ - Windows API │
└─────────────────────────────────────────┘
```
## 🔐 数据流图
### 初始化流程
```
main()
├─> CertificateConfig::GetClientCertificate()
│ │
│ └─> return g_clientCert
├─> SSLClientConnection::Initialize(cert, key, ca, pwd)
│ │
│ ├─> SSL_CTX_new(TLS_client_method())
│ │
│ ├─> CertificateManager::LoadCertificateFromMemory(ca)
│ │ │
│ │ ├─> BIO_new_mem_buf()
│ │ ├─> PEM_read_bio_X509()
│ │ └─> return X509*
│ │
│ ├─> SSL_CTX_use_certificate()
│ │
│ └─> SSL_CTX_use_PrivateKey()
└─> SSLClientConnection::Connect(address, port)
├─> socket() → SOCKET
├─> connect() → TCP连接
├─> SSL_new() → SSL*
├─> SSL_set_fd()
└─> SSL_connect() → SSL握手
```
### 数据传输流程
```
main() [用户输入 "1"]
├─> SSLClientConnection::Send("hello")
│ │
│ └─> SSL_write(m_ssl, "hello", 5)
│ │
│ └─> [加密] → 网络发送
└─> SSLClientConnection::Receive(buffer, size)
└─> SSL_read(m_ssl, buffer, size)
└─> 网络接收 → [解密] → buffer
```
## 💾 内存布局
```
Stack (栈):
┌──────────────────────────────────────┐
│ main() 函数帧 │
│ ├─ SSLClientConnection client; │ <── 完整对象
│ │ ├─ m_sslContext: SSL_CTX* │ <── 指针8字节
│ │ ├─ m_ssl: SSL* │ <── 指针8字节
│ │ ├─ m_socket: SOCKET │ <── 句柄8字节
│ │ ├─ m_isConnected: bool │ <── 布尔1字节
│ │ └─ m_certManager: CertMgr │ <── 空对象1字节
│ │ │
│ └─ char receiveBuffer[1024]; │ <── 缓冲区
└──────────────────────────────────────┘
Heap (堆):
┌──────────────────────────────────────┐
│ SSL_CTX 结构体 ←─ m_sslContext │
│ SSL 结构体 ←─ m_ssl │
│ X509 证书对象 │
│ EVP_PKEY 私钥对象 │
│ ... │
└──────────────────────────────────────┘
析构时自动释放所有堆内存
```
## 📊 编译依赖关系
```
main.cpp
├─ #include "pch.h"
├─ #include "CertificateConfig.h"
└─ #include "SSLClientConnection.h"
SSLClientConnection.cpp
├─ #include "pch.h"
├─ #include "SSLClientConnection.h"
└─ #include "CertificateManager.h"
CertificateManager.cpp
├─ #include "pch.h"
└─ #include "CertificateManager.h"
CertificateConfig.cpp
├─ #include "pch.h"
└─ #include "CertificateConfig.h"
pch.h (预编译头)
├─ #include <winsock2.h>
├─ #include <windows.h>
├─ #include <openssl/ssl.h>
├─ #include <openssl/err.h>
└─ ... (其他系统头文件)
```
## 🧪 单元测试架构(未来扩展)
```cpp
// 伪代码示例
TEST_SUITE(CertificateConfigTest) {
TEST(GetClientCertificate_ReturnsValidCert) {
const char* cert = CertificateConfig::GetClientCertificate();
ASSERT_NOT_NULL(cert);
ASSERT_TRUE(strstr(cert, "BEGIN CERTIFICATE"));
}
}
TEST_SUITE(CertificateManagerTest) {
TEST(LoadCertificateFromMemory_ValidCert_ReturnsX509) {
CertificateManager mgr;
X509* cert = mgr.LoadCertificateFromMemory(validCert);
ASSERT_NOT_NULL(cert);
X509_free(cert);
}
TEST(LoadCertificateFromMemory_InvalidCert_ReturnsNull) {
CertificateManager mgr;
X509* cert = mgr.LoadCertificateFromMemory("invalid");
ASSERT_NULL(cert);
}
}
TEST_SUITE(SSLClientConnectionTest) {
TEST(Initialize_ValidCerts_ReturnsTrue) {
SSLClientConnection client;
bool result = client.Initialize(
validCert, validKey, validCA, "password"
);
ASSERT_TRUE(result);
}
TEST(Connect_InvalidAddress_ReturnsFalse) {
SSLClientConnection client;
client.Initialize(...);
bool result = client.Connect("0.0.0.0", 99999);
ASSERT_FALSE(result);
}
TEST(Send_NotConnected_ReturnsFalse) {
SSLClientConnection client;
bool result = client.Send("hello");
ASSERT_FALSE(result);
}
}
```
## 🔧 配置和扩展点
### 扩展点 1: 支持配置文件
```cpp
// 未来可以添加
class ConfigReader {
public:
ServerConfig ReadFromFile(const std::string& path);
};
// 使用
ConfigReader reader;
ServerConfig config = reader.ReadFromFile("config.json");
client.Connect(config.address, config.port);
```
### 扩展点 2: 日志系统
```cpp
// 未来可以添加
class Logger {
public:
static void Info(const std::string& msg);
static void Error(const std::string& msg);
static void Debug(const std::string& msg);
};
// 在SSLClientConnection中使用
Logger::Info("SSL握手成功");
Logger::Error("连接失败");
```
### 扩展点 3: 异步IO
```cpp
// 未来可以添加
class AsyncSSLClient : public SSLClientConnection {
public:
std::future<bool> ConnectAsync(const char* addr, int port);
std::future<bool> SendAsync(const std::string& data);
std::future<int> ReceiveAsync(char* buffer, int size);
};
```
## 📈 性能考虑
| 方面 | 原版 | 重构版 | 说明 |
|------|------|--------|------|
| **函数调用开销** | 直接调用 | 通过对象调用 | 编译器内联优化,无差异 |
| **内存使用** | 全局变量 | 栈上对象 | 相同(对象很小) |
| **缓存友好性** | 中等 | 好 | 相关数据集中在对象内 |
| **编译优化** | 好 | 好 | 现代编译器优化效果相同 |
**结论**: 重构对运行时性能几乎无影响。
## 📚 代码度量
```
复杂度 (Cyclomatic Complexity):
- 原版 main(): ~25 (高复杂度)
- 重构版 main(): ~8 (低复杂度)
- SSLClientConnection::Connect(): ~12 (中等复杂度)
- CertificateManager::Load*(): ~5 (低复杂度)
耦合度 (Coupling):
- 原版: 高耦合(全局变量)
- 重构版: 低耦合(依赖注入)
内聚度 (Cohesion):
- 原版: 低内聚(功能分散)
- 重构版: 高内聚(功能集中)
```
## 🎓 学习建议
### 初学者
1. 先理解原版 `main.cpp.backup`
2. 运行并测试原版代码
3. 阅读重构版各模块
4. 对比理解设计改进
### 中级开发者
1. 分析类的职责划分
2. 理解RAII资源管理
3. 学习设计模式应用
4. 尝试添加单元测试
### 高级开发者
1. 评估架构设计
2. 考虑性能优化
3. 扩展功能如异步IO
4. 改进错误处理
---
**总结**: 这个重构展示了从"过程式编程"到"面向对象编程"的完整转变是学习现代C++工程实践的绝佳案例。