commit c892ba07f4736891522f7f4e2edf9a7e601a7ae7 Author: yzfh <2811362054@qq.com> Date: Mon Oct 19 15:52:36 2026 +0800 Initial commit: add environment monitoring TCP backend diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7780636 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/bin/ +/data/ +/logs/ +*.log +*.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a145ae1 --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +CC = g++ +CXXFLAGS = -std=c++17 -O2 -Wall -pthread +SRCDIR = src +BINDIR = bin +TARGETS = $(BINDIR)/device_backend $(BINDIR)/console_client +SRC_BACKEND = $(SRCDIR)/server.cpp +SRC_CLIENT = console_client.cpp + +all: $(TARGETS) + +$(BINDIR): + mkdir -p $(BINDIR) + +$(BINDIR)/device_backend: $(SRC_BACKEND) | $(BINDIR) + $(CC) $(CXXFLAGS) -o $(BINDIR)/device_backend $(SRC_BACKEND) + +$(BINDIR)/console_client: $(SRC_CLIENT) | $(BINDIR) + $(CC) $(CXXFLAGS) -o $(BINDIR)/console_client $(SRC_CLIENT) + +clean: + rm -f $(TARGETS) backend.log + +.PHONY: all clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..6b5e9ae --- /dev/null +++ b/README.md @@ -0,0 +1,2379 @@ +# 后端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 │ +│ ├── g_clients: std::vector │ +│ ├── g_devices: std::map │ +│ └── 互斥锁: 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 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 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 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 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 lk(g_clients_mutex); + std::cout << "Active connections: " << g_clients.size() << std::endl; + + std::lock_guard 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 total_messages{0}; + std::atomic 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( + 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 + +# 或使用其他端口 +./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 +``` + +## 📈 性能优化 / 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 g_running{true}; + +// 客户端连接管理 +static std::vector g_clients; +static std::mutex g_clients_mutex; + +// 设备管理 +static std::map 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/_.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":"","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":"","status":"","timestamp":"