# LogCap 项目分析文档

## 1. 项目概述

LogCap 是一个专门用于抓取、分析 UDP 数据包并通过 MQTT 协议发送分析结果的网络监控工具。该项目主要用于监控和分析网络设备的通信数据，特别是针对特定协议的设备注册、心跳和状态上报等数据包。

### 1.1 主要功能

- **网络数据包抓取**：使用 SharpPcap 库实时抓取网络接口上的 UDP 数据包
- **数据包分析**：解析 UDP 数据包内容，提取设备信息、命令类型等关键数据
- **MQTT 数据发送**：将分析结果通过 MQTT 协议发送到指定的 MQTT 服务器
- **端点监控**：监控特定 IP 和端口的通信情况
- **设备管理**：处理设备注册、心跳包等特殊数据包
- **缓存管理**：使用内存缓存存储设备信息，提高处理效率

### 1.2 技术栈

- **开发语言**：C#
- **框架**：.NET
- **网络抓包**：SharpPcap
- **MQTT 客户端**：MQTTnet
- **JSON 序列化**：Newtonsoft.Json
- **HTTP 客户端**：RestSharp
- **缓存**：MemoryCache、CSRedis

## 2. 项目结构

LogCap 项目采用模块化设计，将不同功能分散到不同的类和文件中，提高了代码的可维护性和可读性。

```
LogCap/
├── Common/                # 核心功能模块
│   ├── CSRedisCacheHelper.cs  # Redis 缓存辅助类
│   ├── CacheKey.cs            # 缓存键定义
│   ├── DealWithData.cs        # 数据包处理逻辑
│   ├── HttpSend.cs            # MQTT 数据发送
│   ├── LogExecute.cs          # 数据包抓取和处理
│   ├── PubRepository.cs       # 设备管理和监控控制
│   ├── ReadConfig.cs          # 配置文件读取
│   └── TCache.cs              # 缓存管理
├── Entity/                # 数据模型
│   └── Monitor_Host.cs        # 监控主机模型
├── Properties/            # 项目属性
├── Program.cs             # 主程序入口
├── LogCap.csproj          # 项目文件
├── app.json               # 配置文件
└── nlog.config            # 日志配置
```

## 3. 核心功能模块

### 3.1 数据包抓取与分析

**功能说明**：使用 SharpPcap 库抓取网络接口上的 UDP 数据包，并对数据包进行解析和分析。

**实现逻辑**：
1. 在 `LogExecute.cs` 中，通过 `Execute` 方法初始化网络设备并设置过滤器
2. 注册 `device_OnPacketArrival` 事件处理程序，当有数据包到达时触发
3. 在事件处理程序中，解析数据包，提取源/目标 IP、端口和数据内容
4. 调用 `DealWithData.HandleData` 方法处理数据包内容

**关键代码**：
```csharp
// LogExecute.cs: 设备数据包到达事件处理
private static void device_OnPacketArrival(object sender, PacketCapture e)
{
    try
    {
        var rawPacket = e.GetPacket();
        var p = Packet.ParsePacket(rawPacket.LinkLayerType, rawPacket.Data);
        
        // 提取 IP 地址和端口
        IPAddress SourceAddress = ((PacketDotNet.IPv4Packet)pff).SourceAddress;
        ushort SourcePort = ((PacketDotNet.UdpPacket)((PacketDotNet.IPPacket)pff).PayloadPacket).SourcePort;
        var DestinationAddress = ((PacketDotNet.IPv4Packet)pff).DestinationAddress;
        ushort DestinationPort = ((PacketDotNet.UdpPacket)((PacketDotNet.IPPacket)pff).PayloadPacket).DestinationPort;
        
        // 提取数据内容
        byte[] Data = ((PacketDotNet.IPPacket)pff).PayloadPacket.PayloadData;
        
        // 异步处理数据
        Tuple<byte[], IPAddress, ushort, IPAddress, ushort> ddd = new Tuple<byte[], IPAddress, ushort, IPAddress, ushort>(Data, SourceAddress, SourcePort, DestinationAddress, DestinationPort);
        Task.Factory.StartNew((State) =>
        {
            var tf = State as Tuple<byte[], IPAddress, ushort, IPAddress, ushort>;
            DealWithData.HandleData(tf.Item1.ToList(), tf.Item2.ToString(), tf.Item3, tf.Item4.ToString(), tf.Item5);
        }, ddd);
    }
    catch (Exception ex)
    {
        // 异常处理
    }
}
```

### 3.2 数据包处理与解析

**功能说明**：解析 UDP 数据包内容，提取设备信息、命令类型等关键数据，并根据数据包类型进行相应处理。

**实现逻辑**：
1. 在 `DealWithData.cs` 中，`HandleData` 方法接收数据包内容和网络信息
2. 解析数据包头部，提取命令类型、项目代码等信息
3. 根据命令类型（注册、心跳、设备状态等）进行不同处理
4. 调用 `ReallyDealWith` 方法处理具体业务逻辑

**关键代码**：
```csharp
// DealWithData.cs: 处理数据包
public static void HandleData(List<byte> data, string source_ip, ushort source_port, string dest_ip, ushort dest_port)
{
    try
    {
        // 解析数据包头部
        List<byte> Header = data.Take(2).ToList();
        List<byte> Len = data.Skip(2).Take(2).ToList();
        int Len_int = BitConverter.ToInt16(Len.ToArray(), 0);
        List<byte> ID = data.Skip(4).Take(4).ToList();
        List<byte> CMD = data.Skip(8).Take(1).ToList();
        List<byte> Frame = data.Skip(9).Take(2).ToList();
        List<byte> Project_Code = data.Skip(11).Take(2).ToList();
        
        // 提取命令类型
        byte cmdType_byte = CMD[0];
        BLWCommandType cmdtype = (BLWCommandType)cmdType_byte;
        string CommandType = cmdtype.ToString();
        
        // 根据命令类型处理
        if (cmdType_byte == 0x01)
        {
            // 处理注册命令
            if (source_port == ppp && source_ip.Equals(iii))
            {
                ReallyDealWith(true, data, dest_ip, dest_port, CommandType, ConstKey.Send_TX);
            }
            else
            {
                ReallyDealWith(true, data, source_ip, source_port, CommandType);
            }
        }
        else if (cmdType_byte == 0x02)
        {
            // 处理心跳包
            // ...
        }
        else
        {
            // 处理其他命令
            // ...
        }
    }
    catch (Exception ex)
    {
        // 异常处理
    }
}
```

### 3.3 MQTT 数据发送

**功能说明**：将分析结果通过 MQTT 协议发送到指定的 MQTT 服务器。

**实现逻辑**：
1. 在 `HttpSend.cs` 中，`SendLog` 和 `SendLog_2` 方法接收处理后的数据
2. 将数据转换为 `MonitorLog` 对象并序列化为 JSON 字符串
3. 通过 MQTT 客户端将 JSON 数据发布到指定的 MQTT 主题

**关键代码**：
```csharp
// HttpSend.cs: 发送 MQTT 数据
public static async void SendLog(string xiaodu, string tianmao, string MyCommandType, long hotel_code, int host_id, string roomnumber, string hostnumber, string WWW_IP, int WWW_Port, string lan_ip, int lan_port, string mac, string send_or_receive, string dataHex)
{
    try
    {
        string ti = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
        MonitorLog mm = new MonitorLog();
        // 设置监控日志对象属性
        mm.HotelCode = hotel_code;
        mm.HostID = host_id;
        mm.HostNumber = hostnumber;
        mm.RoomNo = roomnumber;
        // ... 其他属性设置
        
        // 序列化为 JSON
        string str = Newtonsoft.Json.JsonConvert.SerializeObject(mm);
        
        // 发送到 MQTT 服务器
        await Program.mqttClient.PublishStringAsync(debug_log_report_mqtt_topic, str);
    }
    catch (Exception ex)
    {
        Console.WriteLine("发送MQTT数据出错：" + ex.Message);
    }
}
```

### 3.4 MQTT 客户端管理

**功能说明**：管理 MQTT 客户端连接，包括初始化、连接、重连和订阅主题。

**实现逻辑**：
1. 在 `Program.cs` 中，`Start_MqttClient` 方法初始化 MQTT 客户端
2. 设置 MQTT 服务器地址、端口、用户名和密码
3. 注册 `ApplicationMessageReceivedAsync` 和 `DisconnectedAsync` 事件处理程序
4. 连接到 MQTT 服务器并订阅指定主题

**关键代码**：
```csharp
// Program.cs: 启动 MQTT 客户端
async public static Task Start_MqttClient()
{
    try
    {
        var mqttFactory = new MqttClientFactory();
        
        // 读取配置
        string? ip = ReadConfig.Instance.MQTT_ServerIP;
        int? port = ReadConfig.Instance.MQTT_ServerPort;
        string? username = ReadConfig.Instance.MQTT_User;
        string? pwd = ReadConfig.Instance.MQTT_PassWord;
        
        // 创建客户端 ID
        string lid = Guid.NewGuid().ToString("N");
        string ID = $"logmonitor_{lid}";
        mqttClient = mqttFactory.CreateMqttClient();
        
        // 设置连接选项
        var mqttClientOptions = new MqttClientOptionsBuilder()
            .WithClientId(ID)
            .WithTcpServer(ip, port)
            .WithCredentials(username, pwd)
            .WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V500)
            .Build();
        
        // 注册事件处理程序
        mqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync;
        mqttClient.DisconnectedAsync += MqttClient_DisconnectedAsync;
        
        // 连接到 MQTT 服务器
        await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
        
        // 订阅主题
        var subscribeOptions = new MqttClientSubscribeOptions();
        var topicFilter = new MqttTopicFilter
        {
            Topic = "blw/logmonitor/delete/report"
        };
        subscribeOptions.TopicFilters.Add(topicFilter);
        await mqttClient.SubscribeAsync(subscribeOptions, CancellationToken.None);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Start_MqttClient: " + ex.Message);
    }
}
```

### 3.5 设备管理与监控

**功能说明**：管理网络设备，包括设备列表获取、监控启动和停止。

**实现逻辑**：
1. 在 `PubRepository.cs` 中，`GetDeviceList` 方法获取可用的网络设备列表
2. `StartMonitor` 方法启动指定设备的监控
3. `StopMonitor` 方法停止监控并释放资源

**关键代码**：
```csharp
// PubRepository.cs: 启动监控
public static void StartMonitor(int i)
{
    PubRepository.log = new LogExecute();
    PubRepository.log.Execute(i);
}

// PubRepository.cs: 停止监控
public static void StopMonitor()
{
    try
    {
        PubRepository.liveDevice.StopCapture();
        PubRepository.liveDevice.Dispose();
        PubRepository.log = null;
    }
    catch (Exception)
    {
        // 异常处理
    }
}
```

## 4. 工作流程

1. **程序启动**：
   - 初始化缓存，从 Redis 获取监控主机列表和端点监控列表
   - 启动 MQTT 客户端，连接到 MQTT 服务器
   - 启动定时任务，定期更新缓存和发送心跳包

2. **设备选择**：
   - 列出可用的网络设备
   - 用户选择要监控的网络设备（当前硬编码为 3）

3. **监控开始**：
   - 启动选定设备的监控
   - 设置 UDP 数据包过滤器
   - 注册数据包到达事件处理程序

4. **数据包处理**：
   - 当有 UDP 数据包到达时，触发事件处理程序
   - 解析数据包，提取源/目标 IP、端口和数据内容
   - 根据命令类型进行相应处理
   - 提取设备信息，查询房间信息（如果需要）
   - 将处理结果通过 MQTT 发送

5. **监控维护**：
   - 定时更新缓存中的监控主机列表和端点监控列表
   - 检测 MQTT 连接状态，断开时自动重连
   - 定期发送心跳包，保持 MQTT 连接活跃

6. **程序结束**：
   - 停止监控
   - 释放资源

## 5. 配置文件

LogCap 项目使用 `app.json` 文件存储配置信息，主要包括以下配置项：

| 配置项 | 说明 | 默认值 |
|-------|------|-------|
| monitor_filter | 网络数据包过滤器 | - |
| monitor_server_ip | 监控服务器 IP | - |
| monitor_server_port | 监控服务器端口 | 3339 |
| MQTT_ServerIP | MQTT 服务器 IP | - |
| MQTT_ServerPort | MQTT 服务器端口 | 1883 |
| MQTT_User | MQTT 用户名 | - |
| MQTT_PWD | MQTT 密码 | - |
| debug_log_report_mqtt_topic | MQTT 发布主题 | - |
| CRICS_URL | HTTP API 基础 URL | - |

## 6. 技术特点

1. **高效的数据包处理**：
   - 使用异步处理方式，提高数据包处理效率
   - 采用内存缓存，减少重复查询和计算

2. **稳定的 MQTT 连接**：
   - 实现 MQTT 断线重连机制
   - 定期发送心跳包，保持连接活跃

3. **灵活的配置管理**：
   - 使用 JSON 配置文件，便于修改和管理
   - 支持不同环境的配置切换

4. **完善的错误处理**：
   - 捕获并记录异常，确保程序稳定运行
   - 提供详细的日志记录，便于问题排查

5. **模块化设计**：
   - 功能模块分离，便于维护和扩展
   - 代码结构清晰，易于理解和修改

## 7. 应用场景

LogCap 项目适用于以下场景：

1. **网络设备监控**：实时监控网络设备的通信情况，包括设备注册、心跳和状态上报
2. **网络故障排查**：通过分析网络数据包，快速定位网络故障
3. **设备状态管理**：跟踪设备的在线状态和通信情况
4. **网络流量分析**：统计和分析网络流量，优化网络配置
5. **安全监控**：检测异常网络行为，提高网络安全性

## 8. 代码优化建议

1. **异常处理改进**：
   - 当前代码中存在多处空异常捕获，建议添加具体的异常处理逻辑，提高代码的可维护性和可调试性

2. **配置管理优化**：
   - 建议使用强类型配置类，替代当前的字符串配置项，减少配置错误的可能性

3. **内存管理**：
   - 对于大量数据包的处理，建议使用对象池或其他内存优化技术，减少内存分配和垃圾回收

4. **日志系统**：
   - 建议使用更完善的日志系统，如 NLog 或 Serilog，提供更详细的日志信息

5. **代码结构优化**：
   - 建议将业务逻辑进一步分离，提高代码的可读性和可测试性
   - 考虑使用依赖注入，减少组件之间的耦合

6. **性能优化**：
   - 对于高频数据包的处理，建议使用更高效的数据结构和算法
   - 考虑使用多线程或并行处理，提高处理速度

## 9. 总结

LogCap 是一个功能完善的网络数据包监控和分析工具，通过抓取 UDP 数据包并分析其内容，实现了对网络设备的实时监控和数据采集。该项目使用 C# 和 .NET 框架开发，结合 SharpPcap 和 MQTTnet 等库，实现了高效的数据包处理和传输。

项目的主要优势在于：
- 实时监控网络设备的通信情况
- 高效的数据包处理和分析
- 稳定的 MQTT 数据传输
- 灵活的配置管理
- 模块化的代码结构

LogCap 项目可以作为网络监控系统的核心组件，为网络管理和故障排查提供重要的技术支持。通过进一步优化和扩展，该项目可以应用于更广泛的网络监控场景，为网络运维提供更全面的解决方案。