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

17 KiB
Raw Blame History

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)

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 (静态工厂)

class CertificateConfig {
public:
    // 静态方法,无需实例化
    static const char* GetClientCertificate() { 
        return g_clientCert; 
    }
    
private:
    // 私有构造函数,防止实例化
    CertificateConfig() = default;
    ~CertificateConfig() = default;
};

使用:
const char* cert = CertificateConfig::GetClientCertificate();  // 直接调用

3. Manager Pattern (管理器模式)

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 (外观模式)

// 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>
  └─ ... (其他系统头文件)

🧪 单元测试架构(未来扩展)

// 伪代码示例

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: 支持配置文件

// 未来可以添加
class ConfigReader {
public:
    ServerConfig ReadFromFile(const std::string& path);
};

// 使用
ConfigReader reader;
ServerConfig config = reader.ReadFromFile("config.json");
client.Connect(config.address, config.port);

扩展点 2: 日志系统

// 未来可以添加
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

// 未来可以添加
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++工程实践的绝佳案例。