# 后端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":"