# LyneBox **Repository Path**: tianworktion/lyne-box ## Basic Information - **Project Name**: LyneBox - **Description**: 工作调试软件 - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-29 - **Last Updated**: 2026-08-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # LyneBox ## 介绍 LyneBox 是一款基于 WPF 开发的多功能工作调试软件,集成了多种通信协议和工具,方便开发者进行设备调试、数据采集和网络测试。 ## 功能特性 ### 通信协议 - **Modbus 客户端** - 支持 Modbus RTU/TCP 协议,可读写各种寄存器类型 - **Modbus 服务端** - 模拟 Modbus 从站设备,支持寄存器管理和数据模拟 - **串口通信** - 支持多串口同时操作,支持自定义波特率和数据格式 - **TCP 通信** - 支持客户端/服务端模式,实时数据收发 - **UDP 通信** - 支持数据广播和组播 - **WebSocket** - 支持 WebSocket 客户端通信 ### 网络工具 - **IP 工具** - IP 扫描、ARP 探测、DNS 查询 - **HTTP 客户端** - 支持 GET/POST/PUT/DELETE 请求,自定义请求头 - **端口扫描** - 扫描指定 IP 的开放端口 ### 数据工具 - **数据转换** - 支持各种数据格式转换(十六进制、十进制、ASCII 等) - **文件传输** - 支持文件上传和下载 ### 设备控制 - **控制器管理** - 支持设备发现和控制 ## 软件架构 ``` LyneBox/ ├── Controls/ # UI 控件层 │ ├── ModbusPollControl.xaml(.cs) # Modbus 客户端 │ ├── ModbusServerControl.xaml(.cs) # Modbus 服务端 │ ├── SerialPortControl.xaml(.cs) # 串口通信 │ ├── TcpControl.xaml(.cs) # TCP 通信 │ ├── UdpControl.xaml(.cs) # UDP 通信 │ ├── WebSocketControl.xaml(.cs) # WebSocket 通信 │ ├── HttpClientControl.xaml(.cs) # HTTP 客户端 │ ├── IpToolsControl.xaml(.cs) # IP 工具 │ ├── FileTransferControl.xaml(.cs) # 文件传输 │ ├── DataConverterControl.xaml(.cs) # 数据转换 │ └── ControllerControl.xaml(.cs) # 控制器管理 ├── Services/ # 业务逻辑层 │ ├── ModbusService.cs # Modbus 客户端服务 │ ├── ModbusServerService.cs # Modbus 服务端服务 │ ├── SerialPortService.cs # 串口服务 │ ├── TcpService.cs # TCP 服务 │ ├── UdpService.cs # UDP 服务 │ ├── WebSocketService.cs # WebSocket 服务 │ ├── HttpClientService.cs # HTTP 服务 │ └── PortScannerService.cs # 端口扫描服务 ├── Models/ # 数据模型层 ├── ViewModels/ # 视图模型层 ├── Utils/ # 工具类 └── Windows/ # 窗口组件 ``` ## 技术栈 ### 运行时与框架 | 组件 | 版本 | 用途 | |:----:|:----:|:----:| | .NET | 8.0 (net8.0-windows) | 运行时框架,目标平台 Windows x86 | | WPF | 内置于 .NET 8 | 界面渲染引擎,基于 XAML 声明式 UI | | C# | 12.0 | 开发语言,启用 Nullable 引用类型与 ImplicitUsings | ### 第三方依赖 | 库 | 版本 | 用途 | |:--:|:----:|:----:| | HandyControl | 3.6.0-rc3 | WPF UI 控件库,提供 WatermarkTextBox、InputDialog 等增强控件 | | MaterialDesignThemes | 5.3.1 | Material Design 风格图标与主题资源 | | FluentModbus | 5.3.2 | Modbus TCP/RTU 协议实现,支持客户端与服务端 | | System.IO.Ports | 10.0.7 | 串口通信(RS232/RS485)底层封装 | ### 原生依赖 | 文件 | 用途 | |:----:|:----:| | CommonToolDll.dll | 光源控制器原生 SDK,通过 P/Invoke 调用 | | ExampleDll.dll | 控制器设备发现与通信原生库 | --- ## 系统架构详解 ### 整体架构 LyneBox 采用 **MVVM + UserControl 分模块** 架构,分为四层: ``` ┌─────────────────────────────────────────────────────┐ │ App (应用入口层) │ │ 全局异常处理 · 日志管理 · 主题资源 · 启动配置 │ ├─────────────────────────────────────────────────────┤ │ MainWindow (主窗口层) │ │ 导航控制 · 控件延迟实例化 · 连接状态聚合 · 主题切换 │ ├──────────────────────┬──────────────────────────────┤ │ Controls (UI 控件层) │ ViewModels (视图模型层) │ │ 事件订阅/取消订阅 │ INotifyPropertyChanged │ │ Dispatcher 线程切换 │ ICommand 命令绑定 │ ├──────────────────────┼──────────────────────────────┤ │ Services (业务服务层) │ │ 异步通信 · 事件驱动回调 · CancellationToken 生命周期 │ │ IDisposable 资源释放 · 线程安全并发控制 │ ├─────────────────────────────────────────────────────┤ │ Models (数据模型层) │ │ 数据传输对象 · 配置模型 · 事件参数 │ └─────────────────────────────────────────────────────┘ ``` ### 应用入口层 (App) #### 启动流程 ``` App.OnStartup() ├── 注册全局异常处理器 │ ├── AppDomain.CurrentDomain.UnhandledException (非UI线程异常) │ ├── Dispatcher.UnhandledException (UI线程异常) │ └── TaskScheduler.UnobservedTaskException (未观察任务异常) ├── 初始化日志目录 (%AppData%\LyneBox\Logs\) ├── 清理7天前的旧日志 └── 记录启动日志 ``` #### 日志系统 | 方法 | 写入路径 | 说明 | |:----:|:--------:|:----:| | `App.LogError(message, ex)` | `%AppData%\LyneBox\Logs\error_{yyyyMMdd}.log` | 记录异常类型、消息、堆栈跟踪 | | `App.LogInfo(message)` | 同上 | 记录普通信息 | **设计要点:** 日志存储在用户级 `%AppData%` 目录而非程序安装目录,避免 Program Files 权限限制导致写入失败。 --- ### 主窗口层 (MainWindow) #### 控件实例化策略 MainWindow 采用 **延迟实例化 + 单例缓存** 模式: ```csharp // 每个功能模块首次访问时才创建实例,后续复用同一实例 private TcpControl? _tcpControl; private TcpControl TcpControl => _tcpControl ??= new TcpControl(); ``` | 模块 | 实例化时机 | 实例类型 | |:----:|:---------:|:-------:| | TCP 通信 | 构造函数中立即创建 | `TcpControl` (默认显示) | | UDP / 串口 / Modbus等 | 首次点击导航按钮时创建 | 对应 `UserControl` 子类 | | 设置窗口 | 每次点击重新创建 | `SettingsWindow` (模态对话框) | #### 导航与控件切换 ``` NavButton_Click → ShowControlByTag(tag) ├── 根据 tag 查找已缓存的控件实例 ├── 若不存在则 new 创建 ├── 订阅控件的 ConnectionStatusChanged 事件 └── 设置 MainContentControl.Content = control ``` #### 连接状态聚合 MainWindow 聚合所有控件的连接状态: ```csharp // 每个控件通过事件上报自身连接状态 control.ConnectionStatusChanged += OnConnectionStatusChanged; // MainWindow 维护活动连接列表并更新 UI private void OnConnectionStatusChanged(object sender, ConnectionStatusEventArgs e) { Dispatcher.Invoke(() => { if (e.IsConnected) _activeConnections.Add(e.ConnectionInfo); else _activeConnections.Remove(e.ConnectionInfo); }); } ``` **事件参数类:** `ConnectionStatusEventArgs` 封装 `IsConnected` (bool) 和 `ConnectionInfo` (string)。 #### 窗口关闭 `OnClosed` 事件中遍历所有已创建的控件,调用其清理逻辑(若有),确保服务释放。 --- ### UI 控件层 (Controls) 每个 `UserControl` 遵循统一的生命周期模式: #### 创建规则 | 控件 | Service 创建方式 | 说明 | |:----:|:----------------:|:----:| | `TcpControl` | 构造函数内 `new TcpService()` | 内部创建,不使用 DI 容器 | | `UdpControl` | 构造函数内 `new UdpService()` | 同上 | | `SerialPortControl` | 构造函数内 `new SerialPortService()` | 同上 | | `ModbusPollControl` | 构造函数内 `new ModbusService()` + `new ConfigService()` | 同时创建两个服务 | | `ModbusServerControl` | 构造函数内 `new ModbusServerService()` | 同上 | | `WebSocketControl` | 构造函数内 `new WebSocketService()` | 同上 | | `HttpClientControl` | 构造函数内 `new HttpClientService()` | 同上 | | `IpToolsControl` | 构造函数内创建多个服务 | `PortScannerService`、`NetworkMonitorService`、`ArpSpoofDetectorService` | #### 事件订阅模式 所有控件在构造函数中订阅 Service 事件,在 `Unloaded` 中取消订阅: ```csharp // 构造函数中订阅 public TcpControl() { InitializeComponent(); _tcpService = new TcpService(); _tcpService.DataReceived += OnDataReceived; _tcpService.ConnectionChanged += OnConnectionChanged; _tcpService.ErrorOccurred += OnErrorOccurred; Loaded += TcpControl_Loaded; Unloaded += TcpControl_Unloaded; } // Unloaded 中取消订阅(防止内存泄漏) private void TcpControl_Unloaded(object sender, RoutedEventArgs e) { _tcpService.DataReceived -= OnDataReceived; _tcpService.ConnectionChanged -= OnConnectionChanged; _tcpService.ErrorOccurred -= OnErrorOccurred; } ``` #### 线程切换 (Dispatcher) Service 中的异步操作在后台线程执行,回调到 UI 时必须通过 `Dispatcher` 切换: ```csharp private void OnDataReceived(byte[] data) { Dispatcher.Invoke(() => { // 在 UI 线程更新界面 TxtReceive.AppendText(...); }); } ``` #### 各控件清理方式 | 控件 | Unloaded 行为 | |:----:|:------------:| | `UdpControl` | 取消订阅 + 调用 `_udpService.Stop()` | | `WebSocketControl` | 取消订阅 + 调用 `Disconnect()` | | `SerialPortControl` | 停止 DispatcherTimer + 取消所有订阅 | | `ModbusPollControl` | 停止 DispatcherTimer + 取消所有订阅 | | `HttpClientControl` | 取消订阅 + 调用 `Dispose()` | | `TcpControl` | 空(单例复用,事件保持订阅) | | `ModbusServerControl` | 空(单例复用,事件保持订阅) | --- ### 业务服务层 (Services) #### 通用设计模式 每个 Service 遵循 **事件驱动 + 异步取消** 模式: ``` Service 生命周期: Start()/Connect() ├── 创建 CancellationTokenSource ├── 启动 Task.Run() 异步任务 └── 触发 ConnectionChanged 事件 后台任务循环 ├── while (!cancellationToken.IsCancellationRequested) ├── 处理数据/接收请求 └── 触发 DataReceived/RequestReceived 事件 Stop()/Disconnect() ├── cancellationToken.Cancel() ├── 等待任务完成 ├── 释放底层资源 (SerialPort/TcpListener/WebSocket) └── 触发 ConnectionChanged(false) 事件 ``` #### 各 Service 详细说明 ##### TcpService / UdpService | 项目 | 说明 | |:----:|:----:| | **事件** | `DataReceived(byte[])`、`ConnectionChanged(bool)`、`ClientConnected(string)`、`ErrorOccurred(string)` | | **异步控制** | `CancellationTokenSource` 控制接收循环 | | **资源销毁** | `Stop()` 中 `Cancel()` + `Dispose()` TcpClient/UdpClient | | **线程安全** | 接收在后台 Task,回调通过事件触发 | ##### SerialPortService | 项目 | 说明 | |:----:|:----:| | **事件** | `DataReceived(byte[])`、`ConnectionChanged(bool)`、`ErrorOccurred(string)` | | **异步控制** | `CancellationTokenSource` 控制串口读取任务 | | **资源销毁** | `Disconnect()` 中 `Cancel()` + `Close()` + `Dispose()` SerialPort | | **特殊处理** | 串口对象在 `Connect()` 时创建,`Disconnect()` 时销毁,不缓存复用 | ##### ModbusService (客户端) | 项目 | 说明 | |:----:|:----:| | **事件** | `DataReceived`、`ConnectionChanged`、`ErrorOccurred`、`TrafficUpdated` | | **异步控制** | 轮询通过 `DispatcherTimer` 在 UI 线程定时触发 | | **资源销毁** | `Disconnect()` 中关闭 ModbusClient | | **线程安全** | 轮询操作在 UI 线程执行,避免跨线程 | ##### ModbusServerService (服务端) | 项目 | 说明 | |:----:|:----:| | **事件** | `ServerStateChanged(bool)`、`RequestReceived(string)`、`RegisterValueChanged`、`ErrorOccurred(string)` | | **异步控制** | `CancellationTokenSource` 控制 TcpListener 接受连接循环 | | **并发安全** | 寄存器数据使用 `ConcurrentDictionary` / `ConcurrentBag` 存储 | | **资源销毁** | `StopAsync()` 中 `Cancel()` + 停止 TcpListener + 清理客户端连接 | | **启动保护** | `StartTcpServerAsync()` 先调用 `await StopAsync()` 确保旧服务完全停止 | ##### WebSocketService | 项目 | 说明 | |:----:|:----:| | **事件** | `DataReceived(string)`、`ConnectionChanged(bool)`、`ClientConnected/Disconnected(string)`、`ErrorOccurred(string)` | | **异步控制** | `CancellationTokenSource` 控制服务端监听和客户端接收 | | **资源销毁** | `StopServer()`/`Disconnect()` 中关闭 Listener + 关闭 WebSocket + 释放资源 | | **双模式** | 支持客户端模式和服务端模式,各有独立的启停逻辑 | ##### HttpClientService | 项目 | 说明 | |:----:|:----:| | **事件** | `ResponseReceived(string)`、`ErrorOccurred(string)` | | **异步控制** | 使用 `async/await` 发送请求,无后台循环 | | **资源销毁** | 实现 `IDisposable`,`Dispose()` 中释放 `HttpClient` | | **特殊处理** | `HttpClient` 在构造函数中创建,整个生命周期复用 | ##### PortScannerService | 项目 | 说明 | |:----:|:----:| | **事件** | `ScanProgress(string, int, bool)`、`ScanCompleted` | | **异步控制** | `CancellationTokenSource` 控制扫描循环 | | **并发模型** | 每个端口使用 `Task.Run` 并行扫描,通过 `SemaphoreSlim` 限制并发数 | | **资源销毁** | `StopScan()` 中 `Cancel()` | ##### ArpSpoofDetectorService | 项目 | 说明 | |:----:|:----:| | **事件** | `StatusChanged(bool)`、`AlertDetected(string)` | | **异步控制** | 使用 `System.Timers.Timer` 周期性检测 | | **资源销毁** | `Stop()` 中 `Dispose()` Timer | ##### NetworkMonitorService | 项目 | 说明 | |:----:|:----:| | **事件** | `NetworkInfoUpdated(string)` | | **异步控制** | 使用 `Timer` 定时刷新网络计数器 | | **资源销毁** | `Stop()` 中 `Dispose()` Timer | ##### ConfigService | 项目 | 说明 | |:----:|:----:| | **无事件** | 纯数据持久化服务 | | **存储路径** | `%AppData%\LyneBox\config\config.json` | | **序列化** | `System.Text.Json`,配置文件不存在时返回默认配置 | --- ### 数据模型层 (Models) | 类 | 用途 | 关键特性 | |:--:|:----:|:-------:| | `AppConfig` | 应用配置 | JSON 序列化/反序列化,包含网络默认值、快捷连接列表、快捷键配置 | | `ModbusRegister` | Modbus 寄存器模型 | 包含地址、类型、数据类型、字节序、值、只读标记 | | `NavigationItem` | 导航菜单项 | 包含图标、标题、标签 | | `ControllerModels` | 控制器设备模型 | 设备发现与管理数据 | | `HttpHeaderItem` | HTTP 请求头 | 键值对模型 | | `ConnectionStatusEventArgs` | 连接状态事件参数 | 继承 `EventArgs`,封装连接状态信息 | ### 视图模型层 (ViewModels) | 类 | 基类 | 用途 | |:--:|:----:|:----:| | `ViewModelBase` | - | 实现 `INotifyPropertyChanged`,提供 `SetProperty()` 和 `OnPropertyChanged()` | | `MainWindowViewModel` | `ViewModelBase` | 主窗口绑定数据,定义导航命令,通过 `NavigationRequested` 事件通知 View | | `RelayCommand` (Utils) | `ICommand` | 通用命令封装,支持 `Execute` 与可选 `CanExecute` | --- ### 内存管理与销毁规则 #### Service 资源释放链 ``` 用户点击"断开/停止" → Control 调用 Service.Stop() / Disconnect() → CancellationTokenSource.Cancel() // 取消后台任务 → await Task 延迟退出 // 等待循环退出 → Dispose 底层资源 │ SerialPort.Close() + Dispose() │ TcpListener.Stop() │ TcpClient.Close() + Dispose() │ WebSocket.CloseAsync() │ Timer.Dispose() → 触发 ConnectionChanged(false) 事件 // 通知 UI 更新状态 ``` #### 控件生命周期 ``` 创建 → 构造函数 new Service() → 订阅 Service 事件 → 注册 Loaded/Unloaded 显示 → Loaded 触发 → 加载配置/刷新数据 隐藏 → Unloaded 触发 → 取消事件订阅(部分控件) → 停止 Timer(部分控件) → Service 实例保留(单例复用) 关闭 → MainWindow.OnClosed → 遍历所有控件 → 调用 Service.Stop()/Dispose() → 释放原生资源 ``` #### 防止内存泄漏的关键规则 1. **事件订阅必须配对取消** — 构造函数中 `+=`,Unloaded 中 `-=` 2. **后台任务必须可取消** — 所有 `Task.Run` 使用 `CancellationToken` 3. **IDisposable 必须调用** — `HttpClientService` 实现了 `IDisposable`,在 Unloaded 中 Dispose 4. **Timer 必须释放** — `DispatcherTimer.Stop()`,`System.Timers.Timer.Dispose()` 5. **串口对象不缓存** — 每次 Connect 创建新实例,Disconnect 时 Dispose ## 安装教程 1. 下载安装包 `LyneBox_Setup_v1.0.9.exe`(位于 installer 目录) 2. 双击运行安装程序 3. 按照安装向导完成安装 4. 启动 LyneBox 应用程序 ### 源码编译 ```bash # 克隆仓库 git clone # 进入项目目录 cd LyneBox # 安装依赖 dotnet restore # 编译项目 dotnet build --configuration Release # 运行项目 dotnet run --project LyneBox ``` ## 使用说明 ### Modbus 客户端 1. 选择通信模式(RTU 或 TCP) 2. 配置串口或网络参数 3. 点击"连接"按钮建立连接 4. 添加寄存器并设置读写属性 5. 点击"开始轮询"进行数据采集 ### Modbus 服务端 1. 选择通信模式(RTU 或 TCP) 2. 配置端口和从站地址 3. 添加寄存器并设置初始值 4. 点击"启动服务"开始监听 ### 串口通信 1. 选择串口和波特率 2. 配置数据位、停止位和校验位 3. 点击"打开串口" 4. 在发送区输入数据并发送 ### 网络工具 1. 切换到对应工具标签页 2. 输入目标 IP 和端口 3. 执行相应操作(扫描、探测、查询等) ## 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request ## 版本记录 | 版本 | 日期 | 说明 | |:----:|:----:|:----:| | v1.0.9 | 2026-07 | 修复剪贴板异常,优化编辑对话框,统一服务端布局 | | v1.0.8 | 2026-07 | 添加 Modbus 服务端功能 | | v1.0.7 | 2026-06 | 添加 HTTP 客户端功能 | | v1.0.6 | 2026-06 | 添加 WebSocket 通信功能 | | v1.0.5 | 2026-05 | 添加 TCP/UDP 通信功能 | | v1.0.0 | 2026-03 | 初始版本 | ## 许可证 MIT License ## 联系方式 如有问题或建议,请通过以下方式联系: - 提交 Issue - 发送邮件