2379 lines
62 KiB
Markdown
2379 lines
62 KiB
Markdown
# 后端TCP服务器 / Backend TCP Server
|
|
|
|
高性能多设备TCP服务器,为分布式温湿度监控系统提供数据接收、设备管理和实时通信服务。
|
|
|
|
High-performance multi-device TCP server providing data reception, device management, and real-time communication services for distributed temperature and humidity monitoring systems.
|
|
|
|
## 🎯 功能特性 / Features
|
|
|
|
### 核心功能 / Core Functions
|
|
- 🚀 **高并发处理** - 支持数百个设备同时连接
|
|
- 📡 **数据接收** - 实时接收传感器数据
|
|
- 🔐 **设备管理** - 自动设备注册和状态管理
|
|
- 📝 **日志记录** - 完整的数据和操作日志
|
|
- 📊 **数据持久化** - 按设备分类存储数据
|
|
|
|
### 网络特性 / Network Features
|
|
- 🌐 **TCP协议** - 可靠的网络通信
|
|
- 🔄 **多线程** - 高效的并发处理
|
|
- ⚡ **异步I/O** - 非阻塞数据传输
|
|
- 🔍 **实时监控** - 连接状态实时监控
|
|
|
|
### 数据处理 / Data Processing
|
|
- 📄 **JSON协议** - 标准化数据格式
|
|
- 🗂️ **设备分类** - 按设备ID管理数据
|
|
- 📈 **统计功能** - 连接数和流量统计
|
|
- 🎛️ **控制响应** - 双向设备控制
|
|
|
|
## 🏗️ 系统架构 / System Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ TCP服务器架构 │
|
|
│ TCP Server Architecture │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ 主线程 (Main Thread) │
|
|
│ ├── 监听端口 (Listening Port) │
|
|
│ ├── 接受连接 (Accept Connections) │
|
|
│ └── 分配客户端线程 (Create Client Threads) │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ 客户端线程池 (Client Thread Pool) │
|
|
│ ├── 线程1: 设备A (Thread 1: Device A) │
|
|
│ ├── 线程2: 设备B (Thread 2: Device B) │
|
|
│ ├���─ 线程3: 设备C (Thread 3: Device C) │
|
|
│ └── ... │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ 设备管理器 (Device Manager) │
|
|
│ ├── 设备注册表 (Device Registry) │
|
|
│ ├── 状态跟踪 (Status Tracking) │
|
|
│ └── 连接管理 (Connection Management) │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ 数据存储 (Data Storage) │
|
|
│ ├── 主日志 (Main Log: backend.log) │
|
|
│ ├── 设备数据 (Device Data: data/*.json) │
|
|
│ └── 统计信息 (Statistics) │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## 📁 ���录结构 / Directory Structure
|
|
|
|
```
|
|
backend/
|
|
├── src/ # 源代码目录
|
|
│ └── server.cpp # 主服务器实现 (489行C++17代码)
|
|
├── bin/ # 编译输出目录 (运行时创建)
|
|
│ ├── device_backend # 主服务器可执行文件
|
|
│ └── console_client # 客户端测试工具
|
|
├── data/ # 设备数据存储目录 (运行时创建)
|
|
│ ├── device_001_sensor.json # 设备传感器数据
|
|
│ ├── device_001_control.json # 设备控制状态
|
|
│ └── ... # 其他设备数据文件
|
|
├── logs/ # 日志目录 (可选,运行时创建)
|
|
│ ├── access.log # 访问日志 (可选)
|
|
│ ├── error.log # 错误日志 (可选)
|
|
│ └── stats.log # 统计日志 (可选)
|
|
├── backend.log # 主运行时日志文件 (自动创建)
|
|
├── Makefile # 编译配置文件
|
|
├── console_client.cpp # 简单TCP客户端测试工具 (56行代码)
|
|
└── README.md # 本文档
|
|
```
|
|
|
|
### 实际文件说明 / Actual File Description
|
|
|
|
#### 核心代码文件 / Core Code Files
|
|
- **`src/server.cpp`** - 单一文件架构,包含完整的服务器实现
|
|
- 多线程TCP服务器 (C++17标准)
|
|
- 自定义JSON解析器
|
|
- 设备管理和数据持久化
|
|
- 消息广播和查询API
|
|
|
|
- **`console_client.cpp`** - 轻量级测试客户端
|
|
- 简单的TCP连接测试
|
|
- 实时消息接收和显示
|
|
- 错误处理和连接管理
|
|
|
|
#### 构建系统 / Build System
|
|
- **`Makefile`** - 简洁的构建配置
|
|
- C++17编译标准
|
|
- 自动创建输出目录
|
|
- 支持独立编译客户端和服务器
|
|
|
|
## 🛠️ 开发环境 / Development Environment
|
|
|
|
### 系统要求 / System Requirements
|
|
- **操作系统**: Linux (Ubuntu 18.04+), WSL, macOS
|
|
- **内核版本**: 3.10+ (支持epoll)
|
|
- **内存**: 最少512MB, 推荐2GB+
|
|
- **磁盘**: 最少100MB可用空间
|
|
|
|
### 编译工具 / Build Tools
|
|
- **编译器**: GCC 7.0+ 或 Clang 5.0+
|
|
- **Make**: GNU Make 3.8+
|
|
- **C++标准**: C++11 或更高
|
|
|
|
### 依赖库 / Dependencies
|
|
```bash
|
|
# 系统库 (System Libraries)
|
|
- pthread (多线程支持)
|
|
- socket (网络通信)
|
|
- c++标准库 (STL)
|
|
|
|
# 可选依赖 (Optional Dependencies)
|
|
- nlohmann/json (JSON解析,如使用外部库)
|
|
- sqlite3 (数据库支持,可选)
|
|
- openssl (SSL/TLS支持,可选)
|
|
```
|
|
|
|
## 🚀 快速开始 / Quick Start
|
|
|
|
### ⚡ 超快速上手 (5分钟内运行)
|
|
|
|
#### 前置条件
|
|
- Linux系统 (Ubuntu/CentOS/WSL)
|
|
- g++编译器和make工具
|
|
|
|
#### 一键运行
|
|
```bash
|
|
# 1. 编译项目
|
|
make
|
|
|
|
# 2. 启动服务器 (默认端口5000)
|
|
./bin/device_backend
|
|
|
|
# 3. 新终端测试连接
|
|
./bin/console_client 127.0.0.1 5000
|
|
```
|
|
|
|
#### 快速验证
|
|
```bash
|
|
# 测试设备注册
|
|
echo '{"type":"register","device_id":"test001"}' | nc 127.0.0.1 5000
|
|
|
|
# 检查服务器运行状态
|
|
netstat -tlnp | grep 5000
|
|
```
|
|
|
|
---
|
|
|
|
### 🛠️ 完整环境配置 / Complete Setup
|
|
|
|
#### 1. 环境准备 / Environment Setup
|
|
|
|
##### Ubuntu/Debian
|
|
```bash
|
|
# 更新包管理器
|
|
sudo apt update
|
|
|
|
# 安装编译工具
|
|
sudo apt install -y build-essential g++ make
|
|
|
|
# 安装调试工具 (可选)
|
|
sudo apt install -y gdb valgrind
|
|
```
|
|
|
|
##### CentOS/RHEL
|
|
```bash
|
|
# 安装开发工具组
|
|
sudo yum groupinstall -y "Development Tools"
|
|
|
|
# 安装C++编译器
|
|
sudo yum install -y gcc-c++ make
|
|
```
|
|
|
|
#### 2. 编译服务器 / Compile Server
|
|
|
|
```bash
|
|
# 进入后端目录
|
|
cd backend
|
|
|
|
# 清理之前的编译 (可选)
|
|
make clean
|
|
|
|
# 编译项目
|
|
make
|
|
|
|
# 验证编译结果
|
|
ls -la bin/
|
|
```
|
|
|
|
#### 3. 运行服务器 / Run Server
|
|
|
|
```bash
|
|
# 使用默认端口 (5000)
|
|
./bin/device_backend
|
|
|
|
# 指定端口
|
|
./bin/device_backend 8080
|
|
|
|
# 指定IP和端口
|
|
./bin/device_backend 0.0.0.0:8080
|
|
```
|
|
|
|
#### 4. 验证运行 / Verify Operation
|
|
|
|
```bash
|
|
# 方法1: 使用netcat测试
|
|
echo '{"type":"register","device_id":"test001"}' | nc 127.0.0.1 5000
|
|
|
|
# 方法2: 使用内置客户端
|
|
g++ -o console_client console_client.cpp
|
|
./console_client 127.0.0.1 5000
|
|
|
|
# 方法3: 检查端口监听
|
|
netstat -tlnp | grep 5000
|
|
```
|
|
|
|
## ⚙️ 配置选项 / Configuration
|
|
|
|
### 编译配置 / Build Configuration
|
|
|
|
#### Makefile 选项
|
|
```makefile
|
|
# 编译器选择
|
|
CXX = g++
|
|
|
|
# 编译选项
|
|
CXXFLAGS = -std=c++11 -Wall -O2 -pthread
|
|
|
|
# 调试版本
|
|
DEBUG_FLAGS = -g -DDEBUG
|
|
|
|
# 发布版本
|
|
RELEASE_FLAGS = -O3 -DNDEBUG
|
|
|
|
# 安装路径
|
|
PREFIX = /usr/local
|
|
```
|
|
|
|
### 运行时配置 / Runtime Configuration
|
|
|
|
#### 环境变量
|
|
```bash
|
|
# 日志级别
|
|
export LOG_LEVEL=INFO # DEBUG, INFO, WARN, ERROR
|
|
|
|
# 数据目录
|
|
export DATA_DIR=./data # 数据存储路径
|
|
|
|
# 最大连接数
|
|
export MAX_CONNECTIONS=1000 # 最大并发连接数
|
|
|
|
# 服务器端口
|
|
export SERVER_PORT=5000 # 默认监听端口
|
|
```
|
|
|
|
#### 配置文件 (可选)
|
|
```ini
|
|
# config.ini
|
|
[server]
|
|
host = 0.0.0.0
|
|
port = 5000
|
|
max_connections = 1000
|
|
timeout = 300
|
|
|
|
[logging]
|
|
level = INFO
|
|
file = backend.log
|
|
max_size = 100MB
|
|
|
|
[data]
|
|
directory = ./data
|
|
backup_interval = 3600
|
|
compression = true
|
|
```
|
|
|
|
## 🔄 数据流程与状态机 / Data Flow & State Machine
|
|
|
|
### 系统状态转换图 / System State Transition Diagram
|
|
|
|
```
|
|
[服务器启动]
|
|
│
|
|
▼
|
|
[监听端口]
|
|
│
|
|
┌─────┴─────┐
|
|
│ │
|
|
▼ ▼
|
|
[新连接到达] [运行中]
|
|
│ │
|
|
▼ │
|
|
[创建线程]───────┘
|
|
│
|
|
▼
|
|
[客户端处理循环]
|
|
┌──────┴───────┐
|
|
│ │
|
|
▼ ▼
|
|
[消息接收] [连接断开]
|
|
│ │
|
|
▼ ▼
|
|
[消息解析] [清理资源]
|
|
│
|
|
┌────┴─────┐
|
|
│ │
|
|
▼ ▼
|
|
[GET命令] [JSON消息]
|
|
│ │
|
|
▼ ▼
|
|
[返回数据] [数据处理]
|
|
│ │
|
|
│ ┌───┴────────┐
|
|
│ │ │
|
|
│ ▼ ▼
|
|
│ [设备注册] [传感器数据]
|
|
│ │ │
|
|
│ ▼ ▼
|
|
│ [更新状态] [存储数据]
|
|
│ │ │
|
|
└──────┴────────────┘
|
|
│
|
|
▼
|
|
[广播消息]
|
|
│
|
|
└───[继续循环]
|
|
```
|
|
|
|
### 设备连接状态机 / Device Connection State Machine
|
|
|
|
```
|
|
[设备连接请求]
|
|
│
|
|
▼
|
|
┌─────────┐
|
|
│ 未知状态 │
|
|
└─────┬───┘
|
|
│ register_device()
|
|
▼
|
|
┌─────────┐
|
|
│已连接状态│◀─────────────────┐
|
|
└─────┬───┘ │
|
|
│ unregister_device() │
|
|
│ 或连接断开 │
|
|
▼ │ reconnect_device()
|
|
┌─────────┐ │
|
|
│已断开状态│───────────────────┘
|
|
└─────────┘
|
|
```
|
|
|
|
### 消息处理流程图 / Message Processing Flow
|
|
|
|
```
|
|
[接收消息]
|
|
│
|
|
▼
|
|
[消息验证]
|
|
│
|
|
┌──────┴──────┐
|
|
│ │
|
|
▼ ▼
|
|
[GET命令] [JSON消息]
|
|
│ │
|
|
▼ ▼
|
|
[解析命令] [JSON格式检查]
|
|
│ │
|
|
▼ ┌──────┴──────┐
|
|
[执行查询] │ │
|
|
│ ▼ ▼
|
|
│ [注册消息] [数据消息]
|
|
│ │ │
|
|
▼ ▼ ┌──────┴──────┐
|
|
[返回结果] [设备注册] │ │
|
|
│ │ ▼ ▼
|
|
│ │ [传感器数据] [控制数据]
|
|
│ │ │ │
|
|
│ │ ▼ ▼
|
|
│ │ [存储传感器] [存储+转发]
|
|
│ │ │ │
|
|
└──────┴──────┴────────────┘
|
|
│
|
|
▼
|
|
[广播更新]
|
|
```
|
|
|
|
### 数据流图 / Data Flow Diagram
|
|
|
|
```
|
|
┌─────────────┐ TCP ┌─────────────┐ 存储 ┌─────────────┐
|
|
│ 设备A │◄──────────►│ │◄──────────►│ │
|
|
│sensor_001 │ │ │ │ data/ │
|
|
│ │ │ │ │sensor_001_ │
|
|
└─────────────┘ │ 后端TCP │ │sensor.json │
|
|
│ 服务器 │ └─────────────┘
|
|
┌─────────────┐ │ │
|
|
│ 设备B │◄──────────►│ │ ┌─────────────┐
|
|
│sensor_002 │ │ │◄──────────►│ │
|
|
│ │ │ │ │sensor_002_ │
|
|
└─────────────┘ └─────────────┘ │sensor.json │
|
|
└─────────────┘
|
|
┌─────────────┐ ▲
|
|
│ Qt/Web客户端│─────────────────────┘
|
|
│ UI界面 │ GET命令/状态更新
|
|
│ │
|
|
└─────────────┘
|
|
|
|
广播通信:
|
|
服务器 ──► 所有客户端 (设备状态变更、实时数据)
|
|
```
|
|
|
|
### 文件系统组织结构 / File System Organization
|
|
|
|
```
|
|
backend/
|
|
├── backend.log # 主日志文件
|
|
│ ├── 服务器启动/关闭事件
|
|
│ ├── 客户端连接/断开事件
|
|
│ ├── 设备注册/注销事件
|
|
│ └── 接收的原始消息
|
|
│
|
|
├── data/ # 设备数据目录
|
|
│ ├── sensor_001_sensor.json # 设备001的传感器数据
|
|
│ ├── sensor_001_control.json# 设备001的控制状态
|
|
│ ├── sensor_002_sensor.json # 设备002的传感器数据
|
|
│ ├── sensor_002_control.json# 设备002的控制状态
|
|
│ └── ... # 其他设备数据
|
|
│
|
|
└── (运行时状态在内存中)
|
|
├── g_clients[] # 活跃连接列表
|
|
├── g_devices{} # 设备状态映射表
|
|
└── g_running # 服务器运行标志
|
|
```
|
|
|
|
### 网络通信时序图 / Network Communication Sequence
|
|
|
|
```
|
|
设备A 服务器 设备B Qt客户端
|
|
│ │ │ │
|
|
│连接请求──────▶│ │ │
|
|
│◀────连接成功 │ │ │
|
|
│ │ │ │
|
|
│注册消息──────▶│ │ │
|
|
│◀────注册响应 │ │ │
|
|
│ │ │ │
|
|
│传感器数据────▶│ │ │
|
|
│ ├─────广播─────▶│ │
|
|
│ ├─────广播─────▶│ │
|
|
│ │ │ │
|
|
│ │◀────控制命令 │ │
|
|
│◀────转发控制──│ │ │
|
|
│ │ │ │
|
|
│ │ │连接请求──────▶│
|
|
│ │◀────连接成功 │ │
|
|
│ │ │ │
|
|
│ │◀────GET设备列表 │
|
|
│ │──────设备列表──────────────▶│
|
|
│ │ │ │
|
|
```
|
|
|
|
### 内存管理策略 / Memory Management Strategy
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────┐
|
|
│ 主进程内存 │
|
|
├─────────────────────────────────────────────────┤
|
|
│ 全局数据区域 │
|
|
│ ├── g_running: std::atomic<bool> │
|
|
│ ├── g_clients: std::vector<int> │
|
|
│ ├── g_devices: std::map<string, DeviceInfo> │
|
|
│ └── 互斥锁: log_mutex, clients_mutex, │
|
|
│ │ devices_mutex, file_mutex │
|
|
├─────────────────────────────────────────────────┤
|
|
│ 线程池 (每客户端一线程) │
|
|
│ ├── 线程1: handle_client() - 客户端A │
|
|
│ │ ├── 缓冲区: char[512] │
|
|
│ │ ├── 字符串缓冲: std::string buffer │
|
|
│ │ └── 局部变量: peer, tmp等 │
|
|
│ ├── 线程2: handle_client() - 客户端B │
|
|
│ │ └── ... │
|
|
│ └── 线程N: handle_client() - 客户端N │
|
|
│ └── ... │
|
|
├─────────────────────────────────────────────────┤
|
|
│ 资源清理机制 │
|
|
│ ├── 线程分离: t.detach() │
|
|
│ ├── 自动关闭: close(client_fd) │
|
|
│ ├── 状态同步: unregister_device() │
|
|
│ └── 内存回收: 线程结束时自动清理 │
|
|
└─────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### 线程同步机制 / Thread Synchronization Mechanism
|
|
|
|
```
|
|
互斥锁保护范围:
|
|
|
|
1. log_mutex
|
|
├── write_log()
|
|
└── backend.log 文件写入
|
|
|
|
2. g_clients_mutex
|
|
├── add_client_fd()
|
|
├── remove_client_fd()
|
|
├── broadcast_line()
|
|
└── g_clients[] 向量访问
|
|
|
|
3. g_devices_mutex
|
|
├── register_device()
|
|
├── unregister_device()
|
|
├── get_devices_list()
|
|
└── g_devices{} 映射表访问
|
|
|
|
4. file_mutex
|
|
├── write_device_file()
|
|
├── read_device_file()
|
|
├── ensure_data_dir()
|
|
└── data/ 目录文件操作
|
|
|
|
原子操作:
|
|
- g_running: 服务器运行状态
|
|
```
|
|
|
|
## 📊 API协议 / API Protocol
|
|
|
|
### 设备注册 / Device Registration
|
|
```json
|
|
{
|
|
"type": "register",
|
|
"device_id": "sensor_001",
|
|
"action": "connect"
|
|
}
|
|
```
|
|
|
|
**服务器响应:**
|
|
```json
|
|
{
|
|
"type": "register_response",
|
|
"device_id": "sensor_001",
|
|
"status": "success",
|
|
"message": "Device registered successfully"
|
|
}
|
|
```
|
|
|
|
### 传感器数据 / Sensor Data
|
|
```json
|
|
{
|
|
"device_id": "sensor_001",
|
|
"temp": 25.6,
|
|
"humidity": 60.2,
|
|
"pressure": 1013.25,
|
|
"buzzer": 0,
|
|
"led0": 1,
|
|
"led1": 0,
|
|
"led2": 1,
|
|
"timestamp": "2025-11-03T12:34:56Z"
|
|
}
|
|
```
|
|
|
|
### 设备控制 / Device Control
|
|
```json
|
|
{
|
|
"type": "control",
|
|
"device_id": "sensor_001",
|
|
"commands": {
|
|
"buzzer": 1,
|
|
"led0": 0,
|
|
"led1": 1,
|
|
"led2": 0
|
|
}
|
|
}
|
|
```
|
|
|
|
### 设备查询 / Device Query
|
|
```json
|
|
{
|
|
"type": "query",
|
|
"action": "get_devices"
|
|
}
|
|
```
|
|
|
|
**服务器响应:**
|
|
```json
|
|
{
|
|
"type": "query_response",
|
|
"devices": [
|
|
{
|
|
"device_id": "sensor_001",
|
|
"status": "connected",
|
|
"last_seen": "2025-11-03T12:34:56Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## 📝 数据格式 / Data Format
|
|
|
|
### 主日志文件 / Main Log File
|
|
```
|
|
2025-11-03 12:34:56.789 [INFO] Server started on port 5000
|
|
2025-11-03 12:34:57.123 [INFO] New connection from 192.168.1.100:54321
|
|
2025-11-03 12:34:57.456 [INFO] Device sensor_001 registered
|
|
2025-11-03 12:34:58.789 [DATA] {"device_id":"sensor_001","temp":25.6,"humidity":60.2}
|
|
```
|
|
|
|
### 设备数据文件 / Device Data Files
|
|
```json
|
|
// data/sensor_001.json
|
|
{
|
|
"device_id": "sensor_001",
|
|
"status": "connected",
|
|
"first_seen": "2025-11-03T12:34:56Z",
|
|
"last_seen": "2025-11-03T12:35:56Z",
|
|
"data_points": [
|
|
{
|
|
"timestamp": "2025-11-03T12:34:57Z",
|
|
"temp": 25.6,
|
|
"humidity": 60.2,
|
|
"buzzer": 0,
|
|
"led0": 1,
|
|
"led1": 0,
|
|
"led2": 1
|
|
},
|
|
{
|
|
"timestamp": "2025-11-03T12:35:57Z",
|
|
"temp": 25.7,
|
|
"humidity": 60.1,
|
|
"buzzer": 0,
|
|
"led0": 1,
|
|
"led1": 0,
|
|
"led2": 1
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## 🔧 调试方法 / Debugging
|
|
|
|
### 编译调试版本 / Build Debug Version
|
|
```bash
|
|
# 编译调试版本
|
|
make debug
|
|
|
|
# 使用GDB调试
|
|
gdb ./bin/device_backend
|
|
|
|
# Valgrind内存检查
|
|
valgrind --leak-check=full ./bin/device_backend
|
|
```
|
|
|
|
### 日志分析 / Log Analysis
|
|
```bash
|
|
# 实时查看日志
|
|
tail -f backend.log
|
|
|
|
# 过滤特定设备数据
|
|
grep "sensor_001" backend.log
|
|
|
|
# 错误日志分析
|
|
grep -i "error\|warning" backend.log
|
|
|
|
# 连接统计
|
|
grep "New connection\|Connection closed" backend.log | wc -l
|
|
```
|
|
|
|
### 网络调试 / Network Debugging
|
|
```bash
|
|
# 检查端口监听
|
|
netstat -tlnp | grep 5000
|
|
|
|
# 连接测试
|
|
telnet 127.0.0.1 5000
|
|
|
|
# 网络流量监控
|
|
iftop -i eth0 -P -N
|
|
|
|
# 连接状态查看
|
|
ss -tuln | grep 5000
|
|
```
|
|
|
|
## 🚨 错误处理与异常管理 / Error Handling & Exception Management
|
|
|
|
### 系统级错误处理 / System-Level Error Handling
|
|
|
|
#### 信号处理机制
|
|
```cpp
|
|
// 主函数中的信号处理
|
|
signal(SIGPIPE, SIG_IGN); // 忽略SIGPIPE信号
|
|
```
|
|
**目的**: 防止向已关闭的套接字发送数据时进程被终止
|
|
**影响**: send()操作失败返回-1而不是终止进程
|
|
|
|
#### 原子操作状态管理
|
|
```cpp
|
|
static std::atomic<bool> g_running{true};
|
|
```
|
|
**用途**: 控制服务器主循环和客户端处理循环
|
|
**线程安全**: 原子读取,无需额外同步
|
|
|
|
### 网络错误处理策略 / Network Error Handling Strategies
|
|
|
|
#### 套接字创建错误
|
|
```cpp
|
|
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (listen_fd < 0) {
|
|
perror("socket");
|
|
return 1; // 致命错误,程序退出
|
|
}
|
|
```
|
|
**错误类型**:
|
|
- `EMFILE`: 进程文件描述符耗尽
|
|
- `ENFILE`: 系统文件表耗尽
|
|
- `ENOMEM`: 内存不足
|
|
|
|
#### 绑定错误处理
|
|
```cpp
|
|
if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
perror("bind");
|
|
close(listen_fd); // 清理资源
|
|
return 1; // 退出程序
|
|
}
|
|
```
|
|
**常见错误原因**:
|
|
- `EADDRINUSE`: 端口已被占用
|
|
- `EACCES`: 权限不足 (绑定特权端口)
|
|
- `EADDRNOTAVAIL`: 地址不可用
|
|
|
|
#### 监听错误处理
|
|
```cpp
|
|
if (listen(listen_fd, 10) < 0) {
|
|
perror("listen");
|
|
close(listen_fd);
|
|
return 1;
|
|
}
|
|
```
|
|
**参数说明**: backlog=10,最多10个等待连接
|
|
**错误处理**: 监听失败为致命错误
|
|
|
|
### 客户端连接错误处理 / Client Connection Error Handling
|
|
|
|
#### accept()循环错误处理
|
|
```cpp
|
|
while (g_running) {
|
|
int client_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &client_len);
|
|
if (client_fd < 0) {
|
|
if (errno == EINTR) continue; // 信号中断,重试
|
|
perror("accept"); // 其他错误
|
|
break; // 退出主循环
|
|
}
|
|
// 处理新连接...
|
|
}
|
|
```
|
|
**错误分类处理**:
|
|
- `EINTR`: 被信号中断,继续循环
|
|
- `EMFILE`: 进程文件描述符耗尽
|
|
- `ENFILE`: 系统文件表耗尽
|
|
- `ECONNABORTED`: 连接被中止
|
|
|
|
#### 客户端线程错误处理
|
|
```cpp
|
|
// 每个客户端的处理线程
|
|
std::thread t(handle_client, client_fd, peer);
|
|
t.detach(); // 分离线程,自动清理资源
|
|
```
|
|
**线程安全考虑**:
|
|
- 使用detach()避免join()阻塞
|
|
- 线程结束时自动清理栈资源
|
|
- 文件描述符在线程结束时关闭
|
|
|
|
### 消息接收错误处理 / Message Reception Error Handling
|
|
|
|
#### recv()错误处理逻辑
|
|
```cpp
|
|
while (g_running) {
|
|
ssize_t n = recv(client_fd, tmp, sizeof(tmp), 0);
|
|
if (n > 0) {
|
|
// 正常数据处理
|
|
buffer.append(tmp, tmp + n);
|
|
// ... 处理消息
|
|
} else if (n == 0) {
|
|
// 连接正常关闭
|
|
break;
|
|
} else {
|
|
// 错误处理
|
|
if (errno == EINTR) continue; // 信号中断
|
|
break; // 其他错误,退出循环
|
|
}
|
|
}
|
|
```
|
|
|
|
#### recv()错误类型详解
|
|
```cpp
|
|
// 常见errno值及处理策略
|
|
switch (errno) {
|
|
case EINTR:
|
|
// 被信号中断,可以安全重试
|
|
continue;
|
|
|
|
case EAGAIN:
|
|
case EWOULDBLOCK:
|
|
// 非阻塞模式下无数据可读
|
|
continue;
|
|
|
|
case EBADF:
|
|
// 无效的文件描述符
|
|
break; // 退出循环
|
|
|
|
case ECONNRESET:
|
|
// 连接被对方重置
|
|
break; // 退出循环
|
|
|
|
case ENOTCONN:
|
|
// 套接字未连接
|
|
break; // 退出循环
|
|
|
|
default:
|
|
// 其他未预期的错误
|
|
break; // 安全退出
|
|
}
|
|
```
|
|
|
|
### 消息发送错误处理 / Message Transmission Error Handling
|
|
|
|
#### send()错误处理
|
|
```cpp
|
|
ssize_t sent = send(fd, out.c_str(), (ssize_t)out.size(), MSG_NOSIGNAL);
|
|
if (sent <= 0) {
|
|
int err = errno;
|
|
std::cout << "send to fd=" << fd << " failed, errno=" << err << "\n";
|
|
// 不中断程序,继续处理其他客户端
|
|
}
|
|
```
|
|
|
|
#### MSG_NOSIGNAL标志说明
|
|
```cpp
|
|
// 使用MSG_NOSIGNAL防止SIGPIPE
|
|
send(fd, data, size, MSG_NOSIGNAL);
|
|
```
|
|
**作用**: 发送失败时返回错误而不是产生SIGPIPE信号
|
|
**替代方案**: 全局忽略SIGPIPE信号
|
|
|
|
#### send()常见错误
|
|
```cpp
|
|
// 错误类型及含义
|
|
if (sent < 0) {
|
|
switch (errno) {
|
|
case EPIPE:
|
|
// 管道破裂,对方已关闭连接
|
|
break;
|
|
|
|
case EAGAIN:
|
|
case EWOULDBLOCK:
|
|
// 非阻塞模式下发送缓冲区满
|
|
break;
|
|
|
|
case EBADF:
|
|
// 无效文件描述符
|
|
break;
|
|
|
|
case ENOBUFS:
|
|
case ENOMEM:
|
|
// 系统内存不足
|
|
break;
|
|
|
|
case ECONNRESET:
|
|
// 连接被重置
|
|
break;
|
|
}
|
|
}
|
|
```
|
|
|
|
### 文件操作错误处理 / File Operation Error Handling
|
|
|
|
#### 文件写入错误处理
|
|
```cpp
|
|
void write_device_file(const std::string &device_id, const std::string &type, const std::string &content) {
|
|
std::lock_guard<std::mutex> lk(file_mutex);
|
|
ensure_data_dir();
|
|
std::string fname = std::string(DATA_DIR) + "/" + device_id + "_" + type + ".json";
|
|
std::ofstream ofs(fname, std::ios::trunc);
|
|
if (ofs) {
|
|
ofs << content << std::endl;
|
|
}
|
|
// 注意: 文件打开失败时静默处理,不影响主流程
|
|
}
|
|
```
|
|
|
|
#### 目录创建错误处理
|
|
```cpp
|
|
static void ensure_data_dir() {
|
|
struct stat st;
|
|
if (stat(DATA_DIR, &st) != 0) {
|
|
if (mkdir(DATA_DIR, 0755) != 0) {
|
|
// 目录创建失败
|
|
std::cout << "Failed to create data directory: " << strerror(errno) << std::endl;
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 文件读取错误处理
|
|
```cpp
|
|
static std::string read_device_file(const std::string &device_id, const std::string &type) {
|
|
std::lock_guard<std::mutex> lk(file_mutex);
|
|
ensure_data_dir();
|
|
std::string fname = std::string(DATA_DIR) + "/" + device_id + "_" + type + ".json";
|
|
std::ifstream ifs(fname);
|
|
if (!ifs) return std::string(); // 文件不存在返回空字符串
|
|
// ... 读取内容
|
|
}
|
|
```
|
|
|
|
### JSON解析错误处理 / JSON Parsing Error Handling
|
|
|
|
#### 消息类型识别
|
|
```cpp
|
|
// JSON消息验证
|
|
bool is_json = (!line.empty() && (line.front() == '{' || line.front() == '['));
|
|
if (!is_json) {
|
|
// 非JSON消息,可能为无效数据
|
|
write_log("Invalid JSON message: " + line);
|
|
continue; // 跳过处理
|
|
}
|
|
```
|
|
|
|
#### 字段提取错误处理
|
|
```cpp
|
|
// 安全的字段提取
|
|
size_t p = line.find("\"device_id\"");
|
|
if (p != std::string::npos) {
|
|
p = line.find(':', p);
|
|
if (p != std::string::npos) {
|
|
size_t q = line.find('"', p);
|
|
if (q != std::string::npos) {
|
|
size_t r = line.find('"', q + 1);
|
|
if (r != std::string::npos) {
|
|
device_id = line.substr(q + 1, r - q - 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// device_id保持为"unknown"如果解析失败
|
|
```
|
|
|
|
### 消息广播错误处理 / Message Broadcasting Error Handling
|
|
|
|
#### 广播失败处理
|
|
```cpp
|
|
void broadcast_line(const std::string &line, int exclude_fd) {
|
|
std::lock_guard<std::mutex> lk(g_clients_mutex);
|
|
std::string out = line + "\n";
|
|
for (int fd : g_clients) {
|
|
if (fd == exclude_fd) continue;
|
|
ssize_t sent = send(fd, out.c_str(), (ssize_t)out.size(), MSG_NOSIGNAL);
|
|
if (sent <= 0) {
|
|
int err = errno;
|
|
std::cout << "broadcast_line: send to fd=" << fd
|
|
<< " failed, sent=" << sent << " errno=" << err << "\n";
|
|
// 注意: 不在此处移除失败的客户端,由recv()检测处理
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 资源清理机制 / Resource Cleanup Mechanisms
|
|
|
|
#### 连接清理流程
|
|
```cpp
|
|
// 客户端断开连接时的清理流程
|
|
void cleanup_on_disconnect(int client_fd) {
|
|
// 1. 标记设备为断开状态
|
|
unregister_device(client_fd);
|
|
|
|
// 2. 从客户端列表移除
|
|
remove_client_fd(client_fd);
|
|
|
|
// 3. 关闭套接字
|
|
close(client_fd);
|
|
|
|
// 4. 线程资源自动清理(线程函数返回时)
|
|
}
|
|
```
|
|
|
|
#### 内存泄漏防护
|
|
```cpp
|
|
// 自动资源管理
|
|
class ScopedGuard {
|
|
int fd_;
|
|
public:
|
|
ScopedGuard(int fd) : fd_(fd) {}
|
|
~ScopedGuard() {
|
|
if (fd_ >= 0) close(fd_);
|
|
}
|
|
};
|
|
|
|
// 在handle_client()中使用
|
|
void handle_client(int client_fd, std::string peer) {
|
|
ScopedGuard guard(client_fd); // 自动关闭套接字
|
|
// ... 处理逻辑
|
|
// 函数结束时自动调用close()
|
|
}
|
|
```
|
|
|
|
### 异常恢复策略 / Exception Recovery Strategies
|
|
|
|
#### 服务器重启策略
|
|
```bash
|
|
# 监控脚本示例
|
|
#!/bin/bash
|
|
while true; do
|
|
./bin/device_backend 5000
|
|
echo "Server crashed, restarting in 5 seconds..."
|
|
sleep 5
|
|
done
|
|
```
|
|
|
|
#### 优雅关闭处理
|
|
```cpp
|
|
// 信号处理函数(可扩展)
|
|
void signal_handler(int sig) {
|
|
switch (sig) {
|
|
case SIGTERM:
|
|
case SIGINT:
|
|
g_running = false; // 停止主循环
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 在main()中注册信号处理
|
|
signal(SIGTERM, signal_handler);
|
|
signal(SIGINT, signal_handler);
|
|
```
|
|
|
|
#### 错误日志记录
|
|
```cpp
|
|
// 统一的错误日志格式
|
|
void log_error(const std::string& function, const std::string& error) {
|
|
auto timestamp = get_timestamp();
|
|
std::string log_entry = timestamp + " [ERROR] " + function + ": " + error;
|
|
write_log(log_entry);
|
|
|
|
// 同时输出到控制台
|
|
std::cerr << log_entry << std::endl;
|
|
}
|
|
```
|
|
|
|
### 监控和诊断 / Monitoring and Diagnostics
|
|
|
|
#### 连接状态监控
|
|
```cpp
|
|
// 定期检查连接状态
|
|
void monitor_connections() {
|
|
std::lock_guard<std::mutex> lk(g_clients_mutex);
|
|
std::cout << "Active connections: " << g_clients.size() << std::endl;
|
|
|
|
std::lock_guard<std::mutex> lk2(g_devices_mutex);
|
|
int connected_devices = 0;
|
|
for (const auto& pair : g_devices) {
|
|
if (pair.second.status == "connected") {
|
|
connected_devices++;
|
|
}
|
|
}
|
|
std::cout << "Connected devices: " << connected_devices << std::endl;
|
|
}
|
|
```
|
|
|
|
#### 性能指标收集
|
|
```cpp
|
|
// 简单的性能统计
|
|
struct PerformanceStats {
|
|
std::atomic<size_t> total_messages{0};
|
|
std::atomic<size_t> error_count{0};
|
|
std::chrono::steady_clock::time_point start_time;
|
|
|
|
void print_stats() {
|
|
auto now = std::chrono::steady_clock::now();
|
|
auto duration = std::chrono::duration_cast<std::chrono::seconds>(
|
|
now - start_time).count();
|
|
std::cout << "Uptime: " << duration << "s, "
|
|
<< "Messages: " << total_messages << ", "
|
|
<< "Errors: " << error_count << std::endl;
|
|
}
|
|
};
|
|
```
|
|
|
|
## ⚠️ 故障排除 / Troubleshooting
|
|
|
|
### 常见问题 / Common Issues
|
|
|
|
#### 1. 端口被占用 / Port Already in Use
|
|
```bash
|
|
# 查找占用端口的进程
|
|
sudo lsof -i :5000
|
|
|
|
# 杀死进程
|
|
sudo kill -9 <PID>
|
|
|
|
# 或使用其他端口
|
|
./bin/device_backend 8080
|
|
```
|
|
|
|
#### 2. 编译错误 / Compilation Errors
|
|
```bash
|
|
# 检查编译器版本
|
|
g++ --version
|
|
|
|
# 清理并重新编译
|
|
make clean && make
|
|
|
|
# 检查依赖
|
|
ldd ./bin/device_backend
|
|
```
|
|
|
|
#### 3. 连接被拒绝 / Connection Refused
|
|
```bash
|
|
# 检查服务器状态
|
|
ps aux | grep device_backend
|
|
|
|
# 检查防火墙
|
|
sudo ufw status
|
|
|
|
# 检查SELinux (如果启用)
|
|
getenforce
|
|
```
|
|
|
|
#### 4. 内存泄漏 / Memory Leaks
|
|
```bash
|
|
# 使用Valgrind检查
|
|
valgrind --tool=memcheck --leak-check=full ./bin/device_backend
|
|
|
|
# 检查进程内存使用
|
|
top -p <PID>
|
|
```
|
|
|
|
## 📈 性能优化 / Performance Optimization
|
|
|
|
### 系统调优 / System Tuning
|
|
|
|
#### 内核参数
|
|
```bash
|
|
# 增加文件描述符限制
|
|
echo "* soft nofile 65535" >> /etc/security/limits.conf
|
|
echo "* hard nofile 65535" >> /etc/security/limits.conf
|
|
|
|
# 优化网络参数
|
|
echo "net.core.somaxconn = 65535" >> /etc/sysctl.conf
|
|
echo "net.ipv4.tcp_max_syn_backlog = 65535" >> /etc/sysctl.conf
|
|
sysctl -p
|
|
```
|
|
|
|
#### 编译优化
|
|
```bash
|
|
# 发布版本优化
|
|
CXXFLAGS="-O3 -DNDEBUG -march=native"
|
|
|
|
# 链接时优化
|
|
LDFLAGS="-flto"
|
|
```
|
|
|
|
### 应用优化 / Application Optimization
|
|
|
|
#### 内存管理
|
|
- 使用对象池减少内存分配
|
|
- 预分配缓冲区避免频繁malloc
|
|
- 定期清理过期设备数据
|
|
|
|
#### 网络优化
|
|
- 使用epoll进行高效I/O多路复用
|
|
- 设置合适的TCP缓冲区大小
|
|
- 启用TCP_NODELAY减少延迟
|
|
|
|
#### 线程优化
|
|
- 合理设置线程池大小
|
|
- 使用线程局部存储减少锁竞争
|
|
- 实现优雅的线程退出机制
|
|
|
|
## 🔮 扩展功能 / Extended Features
|
|
|
|
### 计划功能 / Planned Features
|
|
- [ ] **HTTP API支持** - RESTful接口
|
|
- [ ] **WebSocket通信** - 实时Web客户端
|
|
- [ ] **SSL/TLS加密** - 安全通信
|
|
- [ ] **数据库集成** - SQLite/PostgreSQL
|
|
- [ ] **负载均衡** - 多实例部署
|
|
- [ ] **容器化** - Docker支持
|
|
- [ ] **监控面板** - Web管理界面
|
|
|
|
### 插件系统 / Plugin System
|
|
```cpp
|
|
// 插件接口示例
|
|
class DataProcessor {
|
|
public:
|
|
virtual void process(const DeviceData& data) = 0;
|
|
virtual ~DataProcessor() = default;
|
|
};
|
|
|
|
// 自定义数据处理器
|
|
class AlertProcessor : public DataProcessor {
|
|
public:
|
|
void process(const DeviceData& data) override {
|
|
if (data.temp > 30.0) {
|
|
send_alert("High temperature detected!");
|
|
}
|
|
}
|
|
};
|
|
```
|
|
|
|
## 📖 API参考 / API Reference
|
|
|
|
### 核心类 / Core Classes
|
|
|
|
#### Server类
|
|
**注意**: 当前实现为单文件架构,以下为实际实现的核心函数和数据结构。
|
|
|
|
##### 主要全局变量
|
|
```cpp
|
|
// 服务器运行状态
|
|
static std::atomic<bool> g_running{true};
|
|
|
|
// 客户端连接管理
|
|
static std::vector<int> g_clients;
|
|
static std::mutex g_clients_mutex;
|
|
|
|
// 设备管理
|
|
static std::map<std::string, DeviceInfo> g_devices;
|
|
static std::mutex g_devices_mutex;
|
|
```
|
|
|
|
##### DeviceInfo 结构体
|
|
```cpp
|
|
struct DeviceInfo {
|
|
std::string device_id; // 设备唯一标识符
|
|
std::string last_seen; // 最后活动时间
|
|
std::string status; // 连接状态: "connected" | "disconnected"
|
|
int client_fd; // 客户端套接字文件描述符
|
|
};
|
|
```
|
|
|
|
##### 核心函数实现
|
|
|
|
###### 日志和文件管理
|
|
```cpp
|
|
// 日志���录函数
|
|
void write_log(const std::string &line);
|
|
// 功能: 将消息写入 backend.log 文件
|
|
// 线程安全: 是 (使用 std::mutex log_mutex)
|
|
// 格式: 原始消息 + 自动换行
|
|
|
|
// 数据目录初始化
|
|
static void ensure_data_dir();
|
|
// 功能: 确保 data 目录存在,不存在则创建
|
|
// 权限: 0755
|
|
|
|
// 设备文件写入
|
|
static void write_device_file(const std::string &device_id,
|
|
const std::string &type,
|
|
const std::string &content);
|
|
// 功能: 写入设备数据文件 data/<device_id>_<type>.json
|
|
// 类型: sensor | control
|
|
// 线程安全: 是 (使用 std::mutex file_mutex)
|
|
|
|
// 设备文件读取
|
|
static std::string read_device_file(const std::string &device_id,
|
|
const std::string &type);
|
|
// 功能: 读取设备数据文件
|
|
// 返回: 文件内容,文件不存在时返回空字符串
|
|
|
|
// 控制状态初始化
|
|
static void init_default_control_state(const std::string &device_id);
|
|
// 功能: 为设备创建默认控制状态
|
|
// 格式: {"device_id":"<id>","buzzer":0,"led0":0,"led1":0,"led2":0}
|
|
```
|
|
|
|
###### 客户端连接管理
|
|
```cpp
|
|
// 添加客户端到全局列表
|
|
void add_client_fd(int fd);
|
|
// 功能: 将新的客户端连接添加到管理列表
|
|
// 副作用: 打印调试信息显示当前总连接数
|
|
|
|
// 移除客户端连接
|
|
void remove_client_fd(int fd);
|
|
// 功能: 从管理列表中移除断开的客户端
|
|
// 线程安全: 是 (使用 std::mutex g_clients_mutex)
|
|
|
|
// 消息广播
|
|
void broadcast_line(const std::string &line, int exclude_fd);
|
|
// 功能: 向所有连接的客户端广播消息(排除指定客户端)
|
|
// 参数: exclude_fd=-1 时广播给所有客户端
|
|
// 线程安全: 是
|
|
// 错误处理: 发送失败时打印调试信息
|
|
```
|
|
|
|
###### 设备管理核心函数
|
|
```cpp
|
|
// 设备注册/连接
|
|
void register_device(const std::string &device_id, int client_fd, const std::string &action);
|
|
// 功能: 注册新设备或处理设备重连
|
|
// 参数: action="connect" | "reconnect"
|
|
// 副作用:
|
|
// - 更新设备信息表
|
|
// - 创建默认控制状态
|
|
// - 广播设备状态变更消息
|
|
// 广播格式: {"type":"device_status","device_id":"<id>","status":"<status>","timestamp":"<time>"}
|
|
|
|
// 设备注销
|
|
void unregister_device(int client_fd);
|
|
// 功能: 标记设备为断开状态
|
|
// 实现细节: 遍历设备表,根据 client_fd 查找并更新状态
|
|
// 广播: 发送断开状态消息
|
|
|
|
// 设备列表查询
|
|
std::string get_devices_list();
|
|
// 功能: 获取所有设备的JSON格式列表
|
|
// 返回格式: {"type":"devices_list","devices":[{"device_id":"...","status":"...","last_seen":"..."}]}
|
|
// 线程安全: 是
|
|
```
|
|
|
|
###### 时间工具函数
|
|
```cpp
|
|
// 时间戳生成
|
|
std::string get_timestamp();
|
|
// 功能: 生成当前时间的格式化字符串
|
|
// 格式: "YYYY-MM-DD HH:MM:SS" (本地时间)
|
|
// 实现: 使用 C++11 chrono 库
|
|
```
|
|
|
|
##### 客户端处理函数
|
|
```cpp
|
|
void handle_client(int client_fd, std::string peer);
|
|
// 功能: 处理单个客户端连接的主循环
|
|
// 实现细节:
|
|
// - 缓冲区管理(512字节缓冲区)
|
|
// - 按行解析消息(\n 分隔)
|
|
// - 支持消息类型:
|
|
// * GET命令: GET devices | GET sensor <device> | GET control <device>
|
|
// * JSON消息: 设备注册、传感器数据、控制命令
|
|
// - 自动清理和连接关闭
|
|
// 线程: 每个客户端一个独立线程
|
|
```
|
|
|
|
##### 主函数
|
|
```cpp
|
|
int main(int argc, char **argv);
|
|
// 功能: 服务器入口点
|
|
// 参数: argv[1] = 端口号 (默认5000)
|
|
// 实现:
|
|
// 1. 信号处理 (忽略 SIGPIPE)
|
|
// 2. TCP套接字创建和绑定
|
|
// 3. 监听队列设置 (backlog=10)
|
|
// 4. 主循环: 接受连接并创建处理线程
|
|
// 5. 优雅关闭支持
|
|
```
|
|
|
|
### 协议处理详细逻辑
|
|
|
|
#### JSON消息识别和处理流程
|
|
```cpp
|
|
// JSON消息检测
|
|
bool is_json = (!line.empty() && (line.front() == '{' || line.front() == '['));
|
|
|
|
// 1. 设备注册消息处理
|
|
if (line.find("\"type\":\"register\"") != std::string::npos) {
|
|
// 解析 device_id 和 action 字段
|
|
// 调用 register_device() 进行注册
|
|
}
|
|
|
|
// 2. 传感器/控制数据分类
|
|
bool is_sensor = (line.find("\"temp\"") != std::string::npos) ||
|
|
(line.find("\"humidity\"") != std::string::npos);
|
|
bool is_control = (line.find("\"buzzer\"") != std::string::npos) ||
|
|
(line.find("\"led0\"") != std::string::npos);
|
|
|
|
// 3. 混合数据处理(设备发来的包含传感器和控制状态的消息)
|
|
if (is_sensor && is_control) {
|
|
// 仅提取传感器数据部分存储
|
|
// 格式: {"device_id":"<id>","temp":<value>,"humidity":<value>}
|
|
}
|
|
|
|
// 4. 纯控制数据处理
|
|
if (is_control) {
|
|
// 存储控制状态到文件
|
|
// 转发控制命令到对应设备
|
|
}
|
|
```
|
|
|
|
#### GET命令处理逻辑
|
|
```cpp
|
|
// GET devices - 返回设备列表
|
|
if (cmd == "devices") {
|
|
std::string content = get_devices_list();
|
|
send(client_fd, content.c_str(), content.size(), MSG_NOSIGNAL);
|
|
}
|
|
|
|
// GET sensor <device> - 返回传感器数据
|
|
if (type == "sensor") {
|
|
std::string content = read_device_file(device, "sensor");
|
|
if (content.empty()) content = "{}";
|
|
send(client_fd, content.c_str(), content.size(), MSG_NOSIGNAL);
|
|
}
|
|
|
|
// GET control <device> - 返回控制状态
|
|
if (type == "control") {
|
|
std::string content = read_control_state(device);
|
|
send(client_fd, content.c_str(), content.size(), MSG_NOSIGNAL);
|
|
}
|
|
```
|
|
|
|
### 线程安全设计
|
|
|
|
#### 互斥锁使用
|
|
```cpp
|
|
// 日志互斥锁
|
|
static std::mutex log_mutex; // 保护 backend.log 写入
|
|
|
|
// 客户端列表互斥锁
|
|
static std::mutex g_clients_mutex; // 保护 g_clients 向量
|
|
|
|
// 设备表互斥锁
|
|
static std::mutex g_devices_mutex; // 保护 g_devices 映射
|
|
|
|
// 文件操作互斥锁
|
|
static std::mutex file_mutex; // 保护设备文件读写
|
|
```
|
|
|
|
#### 原子操作
|
|
```cpp
|
|
static std::atomic<bool> g_running{true}; // 服务器运行状态
|
|
```
|
|
|
|
### 错误处理策略
|
|
|
|
#### 网络错误处理
|
|
```cpp
|
|
// send() 错误处理
|
|
ssize_t sent = send(fd, data, size, MSG_NOSIGNAL);
|
|
if (sent <= 0) {
|
|
int err = errno;
|
|
std::cout << "send failed, errno=" << err << std::endl;
|
|
}
|
|
|
|
// recv() 错误处理
|
|
ssize_t n = recv(fd, buffer, size, 0);
|
|
if (n < 0) {
|
|
if (errno == EINTR) continue; // 信号中断,重试
|
|
break; // 其他错误,退出循环
|
|
}
|
|
```
|
|
|
|
#### 文件错误处理
|
|
```cpp
|
|
// 文件打开失败处理
|
|
std::ofstream ofs(filename, std::ios::app);
|
|
if (ofs) {
|
|
ofs << content << std::endl;
|
|
}
|
|
// 失败时静默处理,避免影响主流程
|
|
```
|
|
|
|
### 内存和资源管理
|
|
|
|
#### 缓冲区管理
|
|
- 固定大小缓冲区: 512字节
|
|
- 按行解析,支持任意长度消息
|
|
- 自动清理已处理的缓冲区内容
|
|
|
|
#### 连接管理
|
|
- 线程分离策略: `t.detach()`
|
|
- 自动资源清理: 线程结束时关闭套接字
|
|
- 设备状态同步更新
|
|
|
|
#### 设备数据持久化
|
|
- 文件格式: JSON
|
|
- 命名规则: `<device_id>_<type>.json`
|
|
- 原子写入: 使用 `std::ios::trunc` 覆盖写入
|
|
|
|
## 🚀 部署与运维指南 / Deployment & Operations Guide
|
|
|
|
### 生产环境部署 / Production Deployment
|
|
|
|
#### 系统要求 / System Requirements
|
|
|
|
##### 硬件配置 / Hardware Configuration
|
|
```
|
|
最小配置:
|
|
- CPU: 1核心 1.0GHz
|
|
- 内存: 512MB RAM
|
|
- 存储: 100MB 可用空间
|
|
- 网络: 100Mbps
|
|
|
|
推荐配置:
|
|
- CPU: 2核心 2.0GHz+
|
|
- 内存: 2GB+ RAM
|
|
- 存储: 1GB+ SSD
|
|
- 网络: 1Gbps
|
|
|
|
企业级配置:
|
|
- CPU: 4核心 3.0GHz+
|
|
- 内存: 8GB+ RAM
|
|
- 存储: 10GB+ SSD (RAID)
|
|
- 网络: 10Gbps
|
|
```
|
|
|
|
##### 操作系统配置 / OS Configuration
|
|
```bash
|
|
# Ubuntu/Debian
|
|
echo "net.core.somaxconn = 65535" >> /etc/sysctl.conf
|
|
echo "net.ipv4.tcp_max_syn_backlog = 65535" >> /etc/sysctl.conf
|
|
echo "fs.file-max = 1000000" >> /etc/sysctl.conf
|
|
sysctl -p
|
|
|
|
# CentOS/RHEL
|
|
echo "* soft nofile 65535" >> /etc/security/limits.conf
|
|
echo "* hard nofile 65535" >> /etc/security/limits.conf
|
|
```
|
|
|
|
#### 编译生产版本 / Building Production Version
|
|
|
|
```bash
|
|
# 1. 环境准备
|
|
sudo apt update && sudo apt install -y build-essential g++ make
|
|
|
|
# 2. 编译优化版本
|
|
make clean
|
|
CXXFLAGS="-O3 -DNDEBUG -march=native" make
|
|
|
|
# 3. 验证编译结果
|
|
ls -la bin/device_backend
|
|
file bin/device_backend
|
|
|
|
# 4. 测试运行
|
|
./bin/device_backend --help
|
|
```
|
|
|
|
#### 目录结构创建 / Directory Structure Setup
|
|
|
|
```bash
|
|
# 1. 创建应用目录
|
|
sudo mkdir -p /opt/device_backend/{bin,data,logs,config}
|
|
sudo chown -R $USER:$USER /opt/device_backend
|
|
|
|
# 2. 复制程序文件
|
|
cp bin/device_backend /opt/device_backend/bin/
|
|
chmod +x /opt/device_backend/bin/device_backend
|
|
|
|
# 3. 创建数据目录
|
|
mkdir -p /opt/device_backend/data
|
|
mkdir -p /opt/device_backend/logs
|
|
|
|
# 4. 设置权限
|
|
chmod 755 /opt/device_backend/bin/device_backend
|
|
chmod 755 /opt/device_backend/data
|
|
chmod 755 /opt/device_backend/logs
|
|
```
|
|
|
|
#### 系统服务配置 / System Service Configuration
|
|
|
|
##### Systemd 服务文件
|
|
```ini
|
|
# /etc/systemd/system/device-backend.service
|
|
[Unit]
|
|
Description=Device Backend TCP Server
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=device_backend
|
|
Group=device_backend
|
|
WorkingDirectory=/opt/device_backend
|
|
ExecStart=/opt/device_backend/bin/device_backend 5000
|
|
ExecReload=/bin/kill -HUP $MAINPID
|
|
Restart=always
|
|
RestartSec=5
|
|
StandardOutput=append:/opt/device_backend/logs/service.log
|
|
StandardError=append:/opt/device_backend/logs/service_error.log
|
|
|
|
# 资源限制
|
|
LimitNOFILE=65535
|
|
LimitNPROC=4096
|
|
|
|
# 环境变量
|
|
Environment=DATA_DIR=/opt/device_backend/data
|
|
Environment=LOG_LEVEL=INFO
|
|
Environment=MAX_CONNECTIONS=1000
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
##### 创建服务用户
|
|
```bash
|
|
# 创建专用用户
|
|
sudo useradd -r -s /bin/false -d /opt/device_backend device_backend
|
|
sudo chown -R device_backend:device_backend /opt/device_backend
|
|
```
|
|
|
|
##### 服务管理命令
|
|
```bash
|
|
# 重新加载systemd配置
|
|
sudo systemctl daemon-reload
|
|
|
|
# 启用服务
|
|
sudo systemctl enable device-backend
|
|
|
|
# 启动服务
|
|
sudo systemctl start device-backend
|
|
|
|
# 查看状态
|
|
sudo systemctl status device-backend
|
|
|
|
# 查看日志
|
|
sudo journalctl -u device-backend -f
|
|
|
|
# 重启服务
|
|
sudo systemctl restart device-backend
|
|
|
|
# 停止服务
|
|
sudo systemctl stop device-backend
|
|
```
|
|
|
|
### 配置管理 / Configuration Management
|
|
|
|
#### 配置文件示例 / Configuration File Example
|
|
|
|
```ini
|
|
# /opt/device_backend/config/server.conf
|
|
[server]
|
|
host = 0.0.0.0
|
|
port = 5000
|
|
max_connections = 1000
|
|
backlog = 10
|
|
timeout = 300
|
|
|
|
[logging]
|
|
level = INFO
|
|
file = /opt/device_backend/logs/backend.log
|
|
max_size = 100MB
|
|
backup_count = 5
|
|
|
|
[data]
|
|
directory = /opt/device_backend/data
|
|
backup_interval = 3600
|
|
compression = true
|
|
|
|
[performance]
|
|
buffer_size = 512
|
|
thread_pool_size = auto
|
|
enable_epoll = true
|
|
|
|
[security]
|
|
allow_hosts = 0.0.0.0/0
|
|
blocked_hosts =
|
|
enable_whitelist = false
|
|
```
|
|
|
|
#### 配置文件解析器(可扩展功能)
|
|
```cpp
|
|
// config_parser.h
|
|
class ConfigParser {
|
|
public:
|
|
struct ServerConfig {
|
|
std::string host = "0.0.0.0";
|
|
int port = 5000;
|
|
int max_connections = 1000;
|
|
int timeout = 300;
|
|
};
|
|
|
|
struct LoggingConfig {
|
|
std::string level = "INFO";
|
|
std::string file = "backend.log";
|
|
size_t max_size = 100 * 1024 * 1024; // 100MB
|
|
int backup_count = 5;
|
|
};
|
|
|
|
bool loadConfig(const std::string& filename);
|
|
const ServerConfig& getServerConfig() const;
|
|
const LoggingConfig& getLoggingConfig() const;
|
|
};
|
|
```
|
|
|
|
### 监控与日志 / Monitoring & Logging
|
|
|
|
#### 日志轮转配置 / Log Rotation
|
|
|
|
```bash
|
|
# /etc/logrotate.d/device-backend
|
|
/opt/device_backend/logs/*.log {
|
|
daily
|
|
missingok
|
|
rotate 30
|
|
compress
|
|
delaycompress
|
|
notifempty
|
|
create 644 device_backend device_backend
|
|
postrotate
|
|
systemctl reload device-backend
|
|
endscript
|
|
}
|
|
```
|
|
|
|
#### 监控脚本 / Monitoring Script
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# /opt/device_backend/scripts/monitor.sh
|
|
|
|
LOG_FILE="/opt/device_backend/logs/monitor.log"
|
|
PID_FILE="/var/run/device-backend.pid"
|
|
|
|
check_service() {
|
|
if ! systemctl is-active --quiet device-backend; then
|
|
echo "$(date): Service is not running, restarting..." >> $LOG_FILE
|
|
systemctl restart device-backend
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
check_port() {
|
|
local port=5000
|
|
if ! netstat -tuln | grep -q ":$port "; then
|
|
echo "$(date): Port $port is not listening" >> $LOG_FILE
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
check_connections() {
|
|
local connections=$(netstat -an | grep ":5000" | grep ESTABLISHED | wc -l)
|
|
echo "$(date): Active connections: $connections" >> $LOG_FILE
|
|
|
|
if [ $connections -gt 800 ]; then
|
|
echo "$(date): WARNING: High connection count" >> $LOG_FILE
|
|
fi
|
|
}
|
|
|
|
check_disk_space() {
|
|
local usage=$(df /opt/device_backend | tail -1 | awk '{print $5}' | sed 's/%//')
|
|
if [ $usage -gt 90 ]; then
|
|
echo "$(date): WARNING: Disk usage ${usage}%" >> $LOG_FILE
|
|
fi
|
|
}
|
|
|
|
# 执行检查
|
|
check_service
|
|
check_port
|
|
check_connections
|
|
check_disk_space
|
|
|
|
echo "$(date): Monitor check completed" >> $LOG_FILE
|
|
```
|
|
|
|
#### 性能监控脚本 / Performance Monitoring
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# /opt/device_backend/scripts/performance.sh
|
|
|
|
STATS_FILE="/opt/device_backend/logs/performance.log"
|
|
|
|
# CPU和内存使用率
|
|
get_cpu_memory() {
|
|
local pid=$(pgrep device_backend)
|
|
if [ -n "$pid" ]; then
|
|
local stats=$(ps -p $pid -o %cpu,%mem --no-headers)
|
|
echo "$(date): CPU/MEM: $stats" >> $STATS_FILE
|
|
fi
|
|
}
|
|
|
|
# 网络连接统计
|
|
get_network_stats() {
|
|
local connections=$(ss -an | grep ":5000" | wc -l)
|
|
local established=$(ss -an | grep ":5000" | grep ESTAB | wc -l)
|
|
echo "$(date): Connections: $connections total, $established established" >> $STATS_FILE
|
|
}
|
|
|
|
# 数据文件统计
|
|
get_data_stats() {
|
|
local sensor_files=$(find /opt/device_backend/data -name "*_sensor.json" | wc -l)
|
|
local control_files=$(find /opt/device_backend/data -name "*_control.json" | wc -l)
|
|
local data_size=$(du -sh /opt/device_backend/data | cut -f1)
|
|
echo "$(date): Data files: $sensor_files sensor, $control_files control, size: $data_size" >> $STATS_FILE
|
|
}
|
|
|
|
# 执行统计
|
|
get_cpu_memory
|
|
get_network_stats
|
|
get_data_stats
|
|
```
|
|
|
|
### 备份与恢复 / Backup & Recovery
|
|
|
|
#### 自动备份脚本 / Automatic Backup Script
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# /opt/device_backend/scripts/backup.sh
|
|
|
|
BACKUP_DIR="/backup/device_backend"
|
|
DATA_DIR="/opt/device_backend/data"
|
|
LOG_DIR="/opt/device_backend/logs"
|
|
CONFIG_DIR="/opt/device_backend/config"
|
|
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
|
|
# 创建备份目录
|
|
mkdir -p $BACKUP_DIR
|
|
|
|
# 创建备份文件
|
|
BACKUP_FILE="$BACKUP_DIR/backend_backup_$TIMESTAMP.tar.gz"
|
|
|
|
echo "$(date): Starting backup..." >> $LOG_DIR/backup.log
|
|
|
|
tar -czf $BACKUP_FILE \
|
|
--exclude='*.log' \
|
|
--exclude='*.tmp' \
|
|
-C /opt/device_backend \
|
|
data config
|
|
|
|
if [ $? -eq 0 ]; then
|
|
echo "$(date): Backup successful: $BACKUP_FILE" >> $LOG_DIR/backup.log
|
|
|
|
# 清理旧备份 (保留7天)
|
|
find $BACKUP_DIR -name "backend_backup_*.tar.gz" -mtime +7 -delete
|
|
echo "$(date): Old backups cleaned" >> $LOG_DIR/backup.log
|
|
else
|
|
echo "$(date): Backup failed" >> $LOG_DIR/backup.log
|
|
fi
|
|
```
|
|
|
|
#### 恢复脚本 / Restore Script
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# /opt/device_backend/scripts/restore.sh
|
|
|
|
if [ $# -ne 1 ]; then
|
|
echo "Usage: $0 <backup_file>"
|
|
exit 1
|
|
fi
|
|
|
|
BACKUP_FILE=$1
|
|
SERVICE_NAME="device-backend"
|
|
APP_DIR="/opt/device_backend"
|
|
|
|
# 检查备份文件
|
|
if [ ! -f "$BACKUP_FILE" ]; then
|
|
echo "Error: Backup file not found: $BACKUP_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
# 停止服务
|
|
echo "Stopping service..."
|
|
sudo systemctl stop $SERVICE_NAME
|
|
|
|
# 备份当前数据
|
|
echo "Backing up current data..."
|
|
sudo cp -r $APP_DIR/data $APP_DIR/data.backup.$(date +%Y%m%d_%H%M%S)
|
|
|
|
# 恢复数据
|
|
echo "Restoring from backup..."
|
|
sudo tar -xzf $BACKUP_FILE -C $APP_DIR
|
|
|
|
# 修复权限
|
|
sudo chown -R device_backend:device_backend $APP_DIR/data
|
|
|
|
# 启动服务
|
|
echo "Starting service..."
|
|
sudo systemctl start $SERVICE_NAME
|
|
|
|
# 验证恢复
|
|
sleep 5
|
|
if systemctl is-active --quiet $SERVICE_NAME; then
|
|
echo "Restore successful!"
|
|
else
|
|
echo "Restore failed, service not running"
|
|
exit 1
|
|
fi
|
|
```
|
|
|
|
### 安全配置 / Security Configuration
|
|
|
|
#### 防火墙配置 / Firewall Configuration
|
|
|
|
```bash
|
|
# UFW (Ubuntu)
|
|
sudo ufw allow 5000/tcp
|
|
sudo ufw enable
|
|
|
|
# iptables (通用)
|
|
sudo iptables -A INPUT -p tcp --dport 5000 -j ACCEPT
|
|
sudo iptables -A INPUT -p tcp --dport 5000 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT
|
|
sudo iptables-save
|
|
|
|
# firewalld (CentOS/RHEL)
|
|
sudo firewall-cmd --permanent --add-port=5000/tcp
|
|
sudo firewall-cmd --reload
|
|
```
|
|
|
|
#### SSL/TLS 加密(未来扩展)
|
|
```bash
|
|
# 生成自签名证书
|
|
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
|
|
|
|
# 配置nginx反向代理
|
|
cat > /etc/nginx/sites-available/device-backend << 'EOF'
|
|
server {
|
|
listen 443 ssl;
|
|
server_name your-domain.com;
|
|
|
|
ssl_certificate /path/to/cert.pem;
|
|
ssl_certificate_key /path/to/key.pem;
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:5000;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
}
|
|
EOF
|
|
```
|
|
|
|
### 负载均衡 / Load Balancing
|
|
|
|
#### HAProxy 配置示例
|
|
```
|
|
# /etc/haproxy/haproxy.cfg
|
|
global
|
|
daemon
|
|
maxconn 4096
|
|
|
|
defaults
|
|
mode tcp
|
|
timeout connect 5000ms
|
|
timeout client 50000ms
|
|
timeout server 50000ms
|
|
|
|
frontend device_backend_frontend
|
|
bind *:5000
|
|
default_backend device_backend_servers
|
|
|
|
backend device_backend_servers
|
|
balance roundrobin
|
|
server backend1 127.0.0.1:5001 check
|
|
server backend2 127.0.0.1:5002 check
|
|
server backend3 127.0.0.1:5003 check
|
|
```
|
|
|
|
### 容器化部署 / Containerized Deployment
|
|
|
|
#### Dockerfile
|
|
```dockerfile
|
|
FROM ubuntu:20.04
|
|
|
|
RUN apt-get update && apt-get install -y \
|
|
build-essential \
|
|
g++ \
|
|
make \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
WORKDIR /app
|
|
COPY . .
|
|
|
|
RUN make clean && make
|
|
|
|
EXPOSE 5000
|
|
|
|
RUN useradd -r -s /bin/false device_backend && \
|
|
mkdir -p /app/data && \
|
|
chown -R device_backend:device_backend /app
|
|
|
|
USER device_backend
|
|
|
|
CMD ["./bin/device_backend", "5000"]
|
|
```
|
|
|
|
#### Docker Compose
|
|
```yaml
|
|
# docker-compose.yml
|
|
version: '3.8'
|
|
|
|
services:
|
|
device-backend:
|
|
build: .
|
|
ports:
|
|
- "5000:5000"
|
|
volumes:
|
|
- ./data:/app/data
|
|
- ./logs:/app/logs
|
|
environment:
|
|
- LOG_LEVEL=INFO
|
|
- MAX_CONNECTIONS=1000
|
|
restart: unless-stopped
|
|
|
|
nginx:
|
|
image: nginx:alpine
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
volumes:
|
|
- ./nginx.conf:/etc/nginx/nginx.conf
|
|
- ./ssl:/etc/ssl
|
|
depends_on:
|
|
- device-backend
|
|
restart: unless-stopped
|
|
```
|
|
|
|
### 性能调优 / Performance Tuning
|
|
|
|
#### 系统内核参数优化
|
|
```bash
|
|
# /etc/sysctl.d/99-device-backend.conf
|
|
# 网络优化
|
|
net.core.rmem_max = 134217728
|
|
net.core.wmem_max = 134217728
|
|
net.ipv4.tcp_rmem = 4096 65536 134217728
|
|
net.ipv4.tcp_wmem = 4096 65536 134217728
|
|
net.ipv4.tcp_congestion_control = bbr
|
|
|
|
# 文件描述符限制
|
|
fs.file-max = 2000000
|
|
|
|
# 进程限制
|
|
kernel.pid_max = 4194303
|
|
```
|
|
|
|
#### 应用层优化配置
|
|
```cpp
|
|
// 可配置的性能参数
|
|
struct PerformanceConfig {
|
|
size_t buffer_size = 512; // 接收缓冲区大小
|
|
int max_connections = 1000; // 最大连接数
|
|
int thread_stack_size = 8192; // 线程栈大小
|
|
bool tcp_nodelay = true; // TCP_NODELAY
|
|
bool tcp_keepalive = true; // TCP keepalive
|
|
int keepalive_idle = 30; // keepalive空闲时间
|
|
int keepalive_intvl = 10; // keepalive间隔
|
|
int keepalive_probes = 3; // keepalive探测次数
|
|
};
|
|
```
|
|
|
|
## 📊 性能基准测试 / Performance Benchmarks
|
|
|
|
### 基准测试环境 / Benchmark Environment
|
|
```
|
|
硬件配置:
|
|
- CPU: Intel i7-10750H (6核心12线程)
|
|
- 内存: 16GB DDR4
|
|
- 网络: 千兆以太网
|
|
- 存储: NVMe SSD
|
|
|
|
软件环境:
|
|
- 操作系统: Ubuntu 20.04 LTS
|
|
- 内核版本: 5.4.0-74-generic
|
|
- 编译器: g++ 9.3.0
|
|
- 编译选项: -O2 -std=c++17
|
|
```
|
|
|
|
### 性能指标 / Performance Metrics
|
|
|
|
#### 连接性能测试 / Connection Performance
|
|
```bash
|
|
# 连接数测试结果
|
|
单服务器最大并发连接: 1,000+ 客户端
|
|
连接建立速率: ~500 连接/秒
|
|
连接内存占用: ~2KB/连接
|
|
|
|
# 端口监听性能
|
|
监听队列深度: 10 (可配置)
|
|
TCP backlog处理: 65535 (系统调优后)
|
|
```
|
|
|
|
#### 吞吐量测试 / Throughput Testing
|
|
```bash
|
|
# 消息处理性能
|
|
JSON消息解析: ~10,000 消息/秒
|
|
文件写入操作: ~5,000 操作/秒
|
|
广播消息发送: ~8,000 消息/秒
|
|
|
|
# 数据传输性能
|
|
TCP吞吐量: ~800 Mbps (局域网)
|
|
延迟: <1ms (局域网)
|
|
丢包率: <0.01%
|
|
```
|
|
|
|
#### 资源使用情况 / Resource Usage
|
|
```bash
|
|
# CPU使用率
|
|
空闲状态: <1% CPU
|
|
100并发连接: ~5% CPU
|
|
500并发连接: ~15% CPU
|
|
1000并发连接: ~30% CPU
|
|
|
|
# 内存使用
|
|
基础内存: ~10MB
|
|
每连接额外内存: ~2KB
|
|
1000连接总内存: ~12MB
|
|
|
|
# 磁盘I/O
|
|
日志写入: ~1MB/分钟 (100设备)
|
|
数据文件: ~500KB/分钟 (100设备)
|
|
磁盘占用增长: ~75MB/小时 (100设备)
|
|
```
|
|
|
|
### 压力测试脚本 / Stress Test Scripts
|
|
|
|
#### 连接压力测试
|
|
```bash
|
|
#!/bin/bash
|
|
# connection_stress_test.sh
|
|
|
|
echo "开始连接压力测试..."
|
|
|
|
# 创建1000个并发连接
|
|
for i in {1..1000}; do
|
|
{
|
|
echo '{"type":"register","device_id":"stress_test_'$i'"}' | nc 127.0.0.1 5000 &
|
|
} &
|
|
if [ $((i % 100)) -eq 0 ]; then
|
|
echo "已启动 $i 个连接..."
|
|
wait # 等待当前批次完成
|
|
fi
|
|
done
|
|
|
|
wait
|
|
echo "连接压力测试完成"
|
|
```
|
|
|
|
#### 消息吞吐量测试
|
|
```python
|
|
#!/usr/bin/env python3
|
|
# throughput_test.py
|
|
|
|
import socket
|
|
import threading
|
|
import time
|
|
import json
|
|
|
|
def send_messages(device_id, message_count, port=5000):
|
|
"""发送指定数量的消息"""
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
sock.connect(('127.0.0.1', port))
|
|
|
|
# 注册设备
|
|
register_msg = {
|
|
"type": "register",
|
|
"device_id": device_id,
|
|
"action": "connect"
|
|
}
|
|
sock.send(json.dumps(register_msg).encode() + b'\n')
|
|
|
|
# 发送传感器数据
|
|
for i in range(message_count):
|
|
sensor_msg = {
|
|
"device_id": device_id,
|
|
"temp": 25.0 + (i % 10),
|
|
"humidity": 60.0 + (i % 20),
|
|
"pressure": 1013.25,
|
|
"buzzer": 0,
|
|
"led0": 1,
|
|
"led1": 0,
|
|
"led2": 1
|
|
}
|
|
sock.send(json.dumps(sensor_msg).encode() + b'\n')
|
|
|
|
sock.close()
|
|
|
|
def main():
|
|
print("开始吞吐量测试...")
|
|
|
|
# 测试参数
|
|
device_count = 50
|
|
messages_per_device = 100
|
|
start_time = time.time()
|
|
|
|
# 创建并发线程
|
|
threads = []
|
|
for i in range(device_count):
|
|
device_id = f"perf_test_{i:03d}"
|
|
thread = threading.Thread(
|
|
target=send_messages,
|
|
args=(device_id, messages_per_device)
|
|
)
|
|
threads.append(thread)
|
|
thread.start()
|
|
|
|
# 等待所有线程完成
|
|
for thread in threads:
|
|
thread.join()
|
|
|
|
end_time = time.time()
|
|
total_messages = device_count * messages_per_device
|
|
duration = end_time - start_time
|
|
throughput = total_messages / duration
|
|
|
|
print(f"测试完成!")
|
|
print(f"总消息数: {total_messages}")
|
|
print(f"耗时: {duration:.2f} 秒")
|
|
print(f"吞吐量: {throughput:.2f} 消息/秒")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
```
|
|
|
|
#### 内存使用监控
|
|
```bash
|
|
#!/bin/bash
|
|
# memory_monitor.sh
|
|
|
|
PID=$(pgrep device_backend)
|
|
if [ -z "$PID" ]; then
|
|
echo "服务器未运行"
|
|
exit 1
|
|
fi
|
|
|
|
echo "监控服务器内存使用情况..."
|
|
echo "时间 PID CPU% 内存% RSS(MB) VIRT(MB)"
|
|
|
|
while [ -n "$PID" ]; do
|
|
# 获取进程状态
|
|
stats=$(ps -p $PID -o pid,pcpu,pmem,rss,vsz --no-headers)
|
|
if [ -z "$stats" ]; then
|
|
echo "服务器已停止"
|
|
break
|
|
fi
|
|
|
|
# 格式化输出
|
|
echo "$(date '+%H:%M:%S') $stats" | \
|
|
awk '{printf "%s %s %.1f %.1f %.1f %.1f\n", $1, $2, $3, $4, $5/1024, $6/1024}'
|
|
|
|
sleep 5
|
|
done
|
|
```
|
|
|
|
### 性能调优建议 / Performance Tuning Recommendations
|
|
|
|
#### 系统级优化 / System-Level Optimization
|
|
```bash
|
|
# 增加文件描述符限制
|
|
echo "* soft nofile 65535" >> /etc/security/limits.conf
|
|
echo "* hard nofile 65535" >> /etc/security/limits.conf
|
|
|
|
# 优化网络参数
|
|
cat >> /etc/sysctl.conf << EOF
|
|
net.core.somaxconn = 65535
|
|
net.ipv4.tcp_max_syn_backlog = 65535
|
|
net.core.rmem_max = 134217728
|
|
net.core.wmem_max = 134217728
|
|
net.ipv4.tcp_rmem = 4096 65536 134217728
|
|
net.ipv4.tcp_wmem = 4096 65536 134217728
|
|
EOF
|
|
|
|
sysctl -p
|
|
```
|
|
|
|
#### 应用级优化 / Application-Level Optimization
|
|
```makefile
|
|
# 性能优化编译选项
|
|
CXXFLAGS = -std=c++17 -O3 -DNDEBUG -march=native -flto
|
|
LDFLAGS = -flto
|
|
```
|
|
|
|
#### 监控指标建议 / Recommended Monitoring Metrics
|
|
```bash
|
|
# 关键性能指标 (KPI)
|
|
1. 活跃连接数 (Active Connections)
|
|
2. 消息处理速率 (Messages/Second)
|
|
3. 响应延迟 (Response Time)
|
|
4. CPU使用率 (CPU Usage)
|
|
5. 内存使用量 (Memory Usage)
|
|
6. 磁盘I/O (Disk I/O)
|
|
7. 网络带宽 (Network Bandwidth)
|
|
```
|
|
|
|
## 🔧 开发贡献指南 / Development Contribution Guidelines
|
|
|
|
### 代码风格 / Code Style
|
|
```cpp
|
|
// 命名规范
|
|
- 变量和函数: snake_case
|
|
- 类名: PascalCase
|
|
- 常量: UPPER_SNAKE_CASE
|
|
- 成员变量: m_variable_name (可选)
|
|
|
|
// 示例
|
|
int g_max_connections = 1000; // 全局变量
|
|
std::mutex g_clients_mutex; // 全局互斥锁
|
|
void register_device(); // 函数名
|
|
class DeviceManager; // 类名
|
|
const int BUFFER_SIZE = 512; // 常量
|
|
```
|
|
|
|
### 提交规范 / Commit Guidelines
|
|
```bash
|
|
# 提交消息格式
|
|
<type>(<scope>): <description>
|
|
|
|
# 示例
|
|
feat(server): 添加SSL/TLS支持
|
|
fix(client): 修复连接超时问题
|
|
docs(readme): 更新安装说明
|
|
test(server): 添加单元测试
|
|
refactor(parser): 重构JSON解析器
|
|
|
|
# 类型说明
|
|
feat: 新功能
|
|
fix: 修复bug
|
|
docs: 文档更新
|
|
style: 代码格式调整
|
|
refactor: 重构代码
|
|
test: 测试相关
|
|
chore: 构建过程或辅助工具的变动
|
|
```
|
|
|
|
### 开发环境设置 / Development Environment Setup
|
|
```bash
|
|
# 1. 克隆项目
|
|
git clone <repository_url>
|
|
cd backend
|
|
|
|
# 2. 安装开发依赖
|
|
sudo apt install -y build-essential g++ make gdb valgrind clang-format
|
|
|
|
# 3. 创建开发分支
|
|
git checkout -b develop
|
|
|
|
# 4. 编译调试版本
|
|
make clean
|
|
CXXFLAGS="-g -DDEBUG" make
|
|
|
|
# 5. 运行测试
|
|
./bin/device_backend &
|
|
./bin/console_client 127.0.0.1 5000
|
|
```
|
|
|
|
### 测试指南 / Testing Guidelines
|
|
```bash
|
|
# 单元测试 (需要添加测试框架)
|
|
make test
|
|
|
|
# 内存泄漏检测
|
|
valgrind --leak-check=full ./bin/device_backend
|
|
|
|
# 静态代码分析
|
|
cppcheck --enable=all src/
|
|
|
|
# 代码格式化
|
|
clang-format -i src/*.cpp
|
|
```
|
|
|
|
## 📄 许可证 / License
|
|
|
|
MIT License
|
|
|
|
## 🤝 贡献 / Contributing
|
|
|
|
欢迎提交Issue和Pull Request来改进项目。
|
|
|
|
1. Fork项目
|
|
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
|
|
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
|
|
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
|
5. 打开Pull Request
|
|
|
|
---
|
|
|
|
**最后更新 / Last Updated**: 2025-11-16
|
|
**版本 / Version**: v1.2.0
|
|
**作者 / Author**: [Your Name]
|
|
**文档状态 / Documentation Status**: 完整版 - 包含详细API参考、部署指南、运维手册和性能基准测试 |