# 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);

// 初始化SSL（HP-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协议理解**
   - 握手过程
   - 证书链验证
   - 密钥交换
   - 数据加密/解密

### 代码行数对比

| 项目 | 代码行数 | 复杂度 |
|------|----------|--------|
| Client（HP-Socket） | ~273行 | 低 |
| Client-Native（原生） | ~450行+ | 中高 |

**结论：使用HP-Socket可以减少40%+的代码量！**

## 常见问题

### Q: 为什么要创建这个项目？
A: 为了学习SSL底层实现，理解HP-Socket的封装价值。

### Q: 实际项目应该用哪个？
A: 实际项目强烈推荐使用HP-Socket！Client-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  
**用途：** 学习和对比  
**状态：** 完成并可运行
