472 lines
17 KiB
Markdown
472 lines
17 KiB
Markdown
# 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++工程实践的绝佳案例。
|